Android アプリケーションが起動するまでの流れ
まとめ
※クリックすると大きな図が開きます
※プロセスの親子関係に注意
$ ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 268 180 c009b74c 0000875c S /init
root 33 1 60924 16448 c009b74c afd0b844 S zygote
system 62 33 130944 27412 ffffffff afd0b6fc S system_server
app_29 122 33 82996 21988 ffffffff afd0c51c S com.android.launcher
app_9 476 33 78500 20568 ffffffff afd0c51c S jp.klab.stone
:
コード読み
以下はソースコードを追った記録です。
なお、例の一件以来 android.git.kernel.org のダウン状態が続いているため、記事中のコードは android.git.linaro.org 上の最新版(2011年 9月末現在)からの引用です。
■ Zygote プロセスの起動(システムブート時) - /init.rc - frameworks/base/cmds/app_process/app_main.cpp ・main() - frameworks/base/core/java/com/android/internal/os/ZygoteInit.java ・main() ■ 1. Launcher のアプリをタップ〜Activity Manager へ要求を投げるまで - packages/apps/Launcher2/src/com/android/launcher2/Launcher.java ・onClick() ・startActivitySafely() - frameworks/base/core/java/android/app/Activity.java ・startActivity() ・startActivityForResult() - frameworks/base/core/java/android/app/Instrumentation.java ・execStartActivity() - frameworks/base/core/java/android/app/ActivityManagerNative.java ・getDefault() ■ 2. Activity Manager が Zygote へプロセス生成要求を投げるまで - frameworks/base/services/java/com/android/server/am/ActivityManagerService.java ・startActivity() - frameworks/base/services/java/com/android/server/am/ActivityStack.java ・startActivityMayWait() ・startActivityLocked() ・startActivityUncheckedLocked() ・startActivityLocked() ・resumeTopActivityLocked() ・startSpecificActivityLocked() - frameworks/base/services/java/com/android/server/am/ActivityManagerService.java ・startProcessLocked() ・startProcessLocked() - frameworks/base/core/java/android/os/Process.java ・start() ・startViaZygote() ・zygoteSendArgsAndGetResult() ■ 3. 要求を受け取った Zygote がプロセスを fork するまで - frameworks/base/core/java/com/android/internal/os/ZygoteInit.java ・runSelectLoopMode() ・acceptCommandPeer() - frameworks/base/core/java/com/android/internal/os/ZygoteConnectionjava ・ZygoteConnection() ・runOnce() ・applyUidSecurityPolicy() ■ 4. fork されたプロセスが Activity Manager へ対象アプリ情報を照会するまで - frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java ・handleChildProc() - frameworks/base/core/java/com/android/internal/os/RuntimeInit.java ・zygoteInit() ・applicationInit() ・invokeStaticMain() - frameworks/base/core/java/com/android/internal/os/ZygoteInit.java ・main() - frameworks/base/core/java/android/app/ActivityThread.java ・main() ・attach() ■ 5. Activity Manager が新規プロセスに起動対象アプリ情報を渡すまで - frameworks/base/services/java/com/android/server/am/ActivityManagerService.java ・attachApplication() ・attachApplicationLocked() ■ 6. 新プロセスが Activity Manager からの情報をもとにアプリを起動するまで - frameworks/base/core/java/android/app/ActivityThread.java ・bindApplication() ・queueOrSendMessage() ・handleMessage() ・handleBindApplication() - frameworks/base/core/java/android/app/LoadedApk.java ・makeApplication() - frameworks/base/core/java/android/app/Instrumentation.java ・newApplication() ・newApplication() ・callApplicationOnCreate()
Zygote プロセスの起動(システムブート時)
/init.rc (実行環境より引用)
: service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd :
frameworks/base/cmds/app_process/app_main.cpp
118 int main(int argc, const char* const argv[]) 119 { : 149 while (i < argc) { 150 const char* arg = argv[i++]; 151 if (!parentDir) { 152 parentDir = arg; 153 } else if (strcmp(arg, "--zygote") == 0) { 154 zygote = true; 155 niceName = "zygote"; 156 } else if (strcmp(arg, "--start-system-server") == 0) { 157 startSystemServer = true; 158 } else if (strcmp(arg, "--application") == 0) { 159 application = true; 160 } else if (strncmp(arg, "--nice-name=", 12) == 0) { 161 niceName = arg + 12; 162 } else { 163 className = arg; 164 break; 165 } 166 } 167 168 if (niceName && *niceName) { 169 setArgv0(argv0, niceName); 170 set_process_name(niceName); 171 } 172 173 runtime.mParentDir = parentDir; 174 175 if (zygote) { 176 runtime.start("com.android.internal.os.ZygoteInit", 177 startSystemServer ? "start-system-server" : "");
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
17 package com.android.internal.os;
:
563 public static void main(String argv[]) {
564 try {
565 VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
566
567 // Start profiling the zygote initialization.
568 SamplingProfilerIntegration.start();
569
570 registerZygoteSocket(); →/dev/socket/zygote を作成
571 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
572 SystemClock.uptimeMillis());
573 preload(); →preloaded-classesに記述されたクラスとリソースをプリロード
574 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
575 SystemClock.uptimeMillis());
576
577 // Finish profiling the zygote initialization.
578 SamplingProfilerIntegration.writeZygoteSnapshot();
579
580 // Do an initial gc to clean up after startup
581 gc();
582
583 // If requested, start system server directly from Zygote
584 if (argv.length != 2) {
585 throw new RuntimeException(argv[0] + USAGE_STRING);
586 }
587
588 if (argv[1].equals("start-system-server")) {
589 startSystemServer(); →system_server プロセスを起動
590 } else if (!argv[1].equals("")) {
591 throw new RuntimeException(argv[0] + USAGE_STRING);
592 }
593
594 Log.i(TAG, "Accepting command socket connections");
595
596 if (ZYGOTE_FORK_MODE) {
597 runForkMode();
598 } else {
599 runSelectLoopMode(); →/dev/socket/zygote からの受信ループへ
600 }
601
602 closeServerSocket();
603 } catch (MethodAndArgsCaller caller) {
604 caller.run();
605 } catch (RuntimeException ex) {
606 Log.e(TAG, "Zygote died with exception", ex);
607 closeServerSocket();
608 throw ex;
609 }
610 }
1. Launcher のアプリをタップ〜Activity Manager へ要求を投げるまで
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
1471 /** 1472 * Launches the intent referred by the clicked shortcut. 1473 * 1474 * @param v The view representing the clicked shortcut. 1475 */ 1476 public void onClick(View v) { 1477 Object tag = v.getTag(); 1478 if (tag instanceof ShortcutInfo) { 1479 // Open shortcut 1480 final Intent intent = ((ShortcutInfo) tag).intent; 1481 int[] pos = new int[2]; 1482 v.getLocationOnScreen(pos); 1483 intent.setSourceBounds(new Rect(pos[0], pos[1], 1484 pos[0] + v.getWidth(), pos[1] + v.getHeight())); 1485 startActivitySafely(intent, tag); 1486 } else if (tag instanceof FolderInfo) { 1487 handleFolderClick((FolderInfo) tag); 1488 } else if (v == mHandleView) { 1489 if (isAllAppsVisible()) { 1490 closeAllApps(true); 1491 } else { 1492 showAllApps(true); 1493 } 1494 } 1495 } 1496 1497 void startActivitySafely(Intent intent, Object tag) { 1498 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1499 try { 1500 startActivity(intent); 1501 } catch (ActivityNotFoundException e) { 1502 Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
frameworks/base/core/java/android/app/Activity.java
2931 @Override 2932 public void startActivity(Intent intent) { 2933 startActivityForResult(intent, -1); 2934 } 2825 public void startActivityForResult(Intent intent, int requestCode) { 2826 if (mParent == null) { 2827 Instrumentation.ActivityResult ar = 2828 mInstrumentation.execStartActivity( 2829 this, mMainThread.getApplicationThread(), mToken, this, 2830 intent, requestCode); 2831 if (ar != null) { 2832 mMainThread.sendActivityResult( 2833 mToken, mEmbeddedID, requestCode, ar.getResultCode(), 2834 ar.getResultData()); 2835 }
frameworks/base/core/java/android/app/Instrumentation.java
1354 public ActivityResult execStartActivity( 1355 Context who, IBinder contextThread, IBinder token, Activity target, 1356 Intent intent, int requestCode) { 1357 IApplicationThread whoThread = (IApplicationThread) contextThread; : 1373 try { 1374 int result = ActivityManagerNative.getDefault() 1375 .startActivity(whoThread, intent, 1376 intent.resolveTypeIfNeeded(who.getContentResolver()), 1377 null, 0, token, target != null ? target.mEmbeddedID : null, 1378 requestCode, false, false); ↑稼動中の Activity Manager へ Binder による IPC 経由で要求を送出 1379 checkStartActivityResult(result, intent); 1380 } catch (RemoteException e) { 1381 } 1382 return null; 1383 }
frameworks/base/core/java/android/app/ActivityManagerNative.java
69 /** 70 * Retrieve the system's default/global activity manager. 71 */ 72 static public IActivityManager getDefault() 73 { 74 if (gDefault != null) { 75 //if (Config.LOGV) Log.v( 76 // "ActivityManager", "returning cur default = " + gDefault); 77 return gDefault; 78 } 79 IBinder b = ServiceManager.getService("activity"); 80 if (Config.LOGV) Log.v( 81 "ActivityManager", "default service binder = " + b); 82 gDefault = asInterface(b); 83 if (Config.LOGV) Log.v( 84 "ActivityManager", "default service = " + gDefault); 85 return gDefault; 86 }
2. Activity Manager が Zygote へプロセス生成要求を投げるまで
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
393 public ActivityStack mMainStack;
:
2064 public final int startActivity(IApplicationThread caller,
2065 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2066 int grantedMode, IBinder resultTo,
2067 String resultWho, int requestCode, boolean onlyIfNeeded,
2068 boolean debug) {
2069 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
2070 grantedUriPermissions, grantedMode, resultTo, resultWho,
2071 requestCode, onlyIfNeeded, debug, null, null);
2072 }
1265 public static final Context main(int factoryTest) {
:
1278 ActivityManagerService m = thr.mService;
1279 mSelf = m;
1280 ActivityThread at = ActivityThread.systemMain();
1281 mSystemThread = at;
1282 Context context = at.getSystemContext();
1283 m.mContext = context;
1284 m.mFactoryTest = factoryTest;
1285 m.mMainStack = new ActivityStack(m, context, true);
:
frameworks/base/services/java/com/android/server/am/ActivityStack.java
2387 final int startActivityMayWait(IApplicationThread caller, 2388 Intent intent, String resolvedType, Uri[] grantedUriPermissions, 2389 int grantedMode, IBinder resultTo, 2390 String resultWho, int requestCode, boolean onlyIfNeeded, 2391 boolean debug, WaitResult outResult, Configuration config) { 2392 // Refuse possible leaked file descriptors 2393 if (intent != null && intent.hasFileDescriptors()) { 2394 throw new IllegalArgumentException("File descriptors passed in Intent"); 2395 } 2396 2397 boolean componentSpecified = intent.getComponent() != null; 2398 2399 // Don't modify the client's object! 2400 intent = new Intent(intent); 2401 2402 // Collect information about the target of the Intent. 2403 ActivityInfo aInfo; 2404 try { 2405 ResolveInfo rInfo = 2406 AppGlobals.getPackageManager().resolveIntent( 2407 intent, resolvedType, 2408 PackageManager.MATCH_DEFAULT_ONLY 2409 | ActivityManagerService.STOCK_PM_FLAGS); 2410 aInfo = rInfo != null ? rInfo.activityInfo : null; 2411 } catch (RemoteException e) { 2412 aInfo = null; 2413 } 2414 2415 if (aInfo != null) { 2416 // Store the found target back into the intent, because now that 2417 // we have it we never want to do this again. For example, if the 2418 // user navigates back to this point in the history, we should 2419 // always restart the exact same activity. 2420 intent.setComponent(new ComponentName( 2421 aInfo.applicationInfo.packageName, aInfo.name)); 2422 2423 // Don't debug things in the system process 2424 if (debug) { 2425 if (!aInfo.processName.equals("system")) { 2426 mService.setDebugApp(aInfo.processName, true, false); 2427 } 2428 } 2429 } 2430 2431 synchronized (mService) { 2432 int callingPid; 2433 int callingUid; 2434 if (caller == null) { 2435 callingPid = Binder.getCallingPid(); 2436 callingUid = Binder.getCallingUid(); 2437 } else { 2438 callingPid = callingUid = -1; 2439 } 2440 2441 mConfigWillChange = config != null 2442 && mService.mConfiguration.diff(config) != 0; 2443 if (DEBUG_CONFIGURATION) Slog.v(TAG, 2444 "Starting activity when config will change = " + mConfigWillChange); 2445 2446 final long origId = Binder.clearCallingIdentity(); 2447 2448 if (mMainStack && aInfo != null && 2449 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG;_CANT_SAVE_STATE) != 0) { 2450 // This may be a heavy-weight process! Check to see if we already 2451 // have another, different heavy-weight process running. : 2514 } 2515 2516 int res = startActivityLocked(caller, intent, resolvedType, 2517 grantedUriPermissions, grantedMode, aInfo, 2518 resultTo, resultWho, requestCode, callingPid, callingUid, 2519 onlyIfNeeded, componentSpecified);
1877 final int startActivityLocked(IApplicationThread caller, 1878 Intent intent, String resolvedType, 1879 Uri[] grantedUriPermissions, 1880 int grantedMode, ActivityInfo aInfo, IBinder resultTo, 1881 String resultWho, int requestCode, 1882 int callingPid, int callingUid, boolean onlyIfNeeded, 1883 boolean componentSpecified) { 1884 1885 int err = START_SUCCESS; 1886 1887 ProcessRecord callerApp = null; 1888 if (caller != null) { 1889 callerApp = mService.getRecordForAppLocked(caller); 1890 if (callerApp != null) { 1891 callingPid = callerApp.pid; 1892 callingUid = callerApp.info.uid; 1893 } else { 1894 Slog.w(TAG, "Unable to find app for caller " + caller 1895 + " (pid=" + callingPid + ") when starting: " 1896 + intent.toString()); 1897 err = START_PERMISSION_DENIED; 1898 } 1899 } 1900 1901 if (err == START_SUCCESS) { 1902 Slog.i(TAG, "Starting: " + intent + " from pid " 1903 + (callerApp != null ? callerApp.pid : callingPid)); 1904 } 1905 1906 ActivityRecord sourceRecord = null; 1907 ActivityRecord resultRecord = null; 1908 if (resultTo != null) { 1909 int index = indexOfTokenLocked(resultTo); 1910 if (DEBUG_RESULTS) Slog.v( 1911 TAG, "Sending result to " + resultTo + " (index " + index + ")"); 1912 if (index >= 0) { 1913 sourceRecord = (ActivityRecord)mHistory.get(index); 1914 if (requestCode >= 0 && !sourceRecord.finishing) { 1915 resultRecord = sourceRecord; 1916 } 1917 } 1918 } 1919 1920 int launchFlags = intent.getFlags(); 1921 1922 if ((launchFlags&Intent.FLAG;_ACTIVITY_FORWARD_RESULT) != 0 1923 && sourceRecord != null) { 1924 // Transfer the result target from the source activity to the new 1925 // one being started, including any failures. 1926 if (requestCode >= 0) { 1927 return START_FORWARD_AND_REQUEST_CONFLICT; 1928 } 1929 resultRecord = sourceRecord.resultTo; 1930 resultWho = sourceRecord.resultWho; 1931 requestCode = sourceRecord.requestCode; 1932 sourceRecord.resultTo = null; 1933 if (resultRecord != null) { 1934 resultRecord.removeResultsLocked( 1935 sourceRecord, resultWho, requestCode); 1936 } 1937 } : 1960 final int perm = mService.checkComponentPermission(aInfo.permission, callingPid, 1961 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid); 1962 if (perm != PackageManager.PERMISSION_GRANTED) { 1963 if (resultRecord != null) { 1964 sendActivityResultLocked(-1, 1965 resultRecord, resultWho, requestCode, 1966 Activity.RESULT_CANCELED, null); 1967 } 1968 String msg = "Permission Denial: starting " + intent.toString() 1969 + " from " + callerApp + " (pid=" + callingPid 1970 + ", uid=" + callingUid + ")" 1971 + " requires " + aInfo.permission; 1972 Slog.w(TAG, msg); 1973 throw new SecurityException(msg); 1974 } : 2002 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, 2003 intent, resolvedType, aInfo, mService.mConfiguration, 2004 resultRecord, resultWho, requestCode, componentSpecified); : 2035 return startActivityUncheckedLocked(r, sourceRecord, 2036 grantedUriPermissions, grantedMode, onlyIfNeeded, true); 2037 }
2039 final int startActivityUncheckedLocked(ActivityRecord r, 2040 ActivityRecord sourceRecord, Uri[] grantedUriPermissions, 2041 int grantedMode, boolean onlyIfNeeded, boolean doResume) { : 2294 boolean newTask = false; 2295 2296 // Should this be considered a new task? 2297 if (r.resultTo == null && !addingToTask 2298 && (launchFlags&Intent.FLAG;_ACTIVITY_NEW_TASK) != 0) { 2299 // todo: should do better management of integers. 2300 mService.mCurTask++; 2301 if (mService.mCurTask <= 0) { 2302 mService.mCurTask = 1; 2303 } 2304 r.task = new TaskRecord(mService.mCurTask, r.info, intent, 2305 (r.info.flags&ActivityInfo.FLAG;_CLEAR_TASK_ON_LAUNCH) != 0); 2306 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 2307 + " in new task " + r.task); 2308 newTask = true; 2309 if (mMainStack) { 2310 mService.addRecentTaskLocked(r.task); 2311 } 2312 2313 } : 2383 startActivityLocked(r, newTask, doResume); 2384 return START_SUCCESS; 2385 }
1349 private final void startActivityLocked(ActivityRecord r, boolean newTask, 1350 boolean doResume) { : 1475 if (doResume) { 1476 resumeTopActivityLocked(null); 1477 } 1478 }
1051 final boolean resumeTopActivityLocked(ActivityRecord prev) { 1052 // Find the first activity that is not finishing. 1053 ActivityRecord next = topRunningActivityLocked(null); : 1343 startSpecificActivityLocked(next, true, true);
594 private final void startSpecificActivityLocked(ActivityRecord r, 595 boolean andResume, boolean checkConfig) { 596 // Is this activity's application already running? 597 ProcessRecord app = mService.getProcessRecordLocked(r.processName, 598 r.info.applicationInfo.uid); 599 600 if (r.launchTime == 0) { 601 r.launchTime = SystemClock.uptimeMillis(); 602 if (mInitialStartTime == 0) { 603 mInitialStartTime = r.launchTime; 604 } 605 } else if (mInitialStartTime == 0) { 606 mInitialStartTime = SystemClock.uptimeMillis(); 607 } 608 609 if (app != null && app.thread != null) { 610 try { 611 realStartActivityLocked(r, app, andResume, checkConfig); 612 return; 613 } catch (RemoteException e) { 614 Slog.w(TAG, "Exception when starting activity " 615 + r.intent.getComponent().flattenToShortString(), e); 616 } 617 618 // If a dead object exception was thrown -- fall through to 619 // restart the application. 620 } 621 622 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, 623 "activity", r.intent.getComponent(), false); 624 }
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
1724 final ProcessRecord startProcessLocked(String processName, 1725 ApplicationInfo info, boolean knownToBeDead, int intentFlags, 1726 String hostingType, ComponentName hostingName, boolean allowWhileBooting) { 1727 ProcessRecord app = getProcessRecordLocked(processName, info.uid); 1728 // We don't have to do anything more if: 1729 // (1) There is an existing application record; and 1730 // (2) The caller doesn't think it is dead, OR there is no thread 1731 // object attached to it so we know it couldn't have crashed; and 1732 // (3) There is a pid assigned to it, so it is either starting or 1733 // already running. : 1752 String hostingNameStr = hostingName != null 1753 ? hostingName.flattenToShortString() : null; 1781 if (app == null) { 1782 app = newProcessRecordLocked(null, info, processName); 1783 mProcessNames.put(processName, info.uid, app); 1784 } else { 1785 // If this is a new package in the process, add the package to the list 1786 app.addPackage(info.packageName); 1787 } : 1801 startProcessLocked(app, hostingType, hostingNameStr); 1802 return (app.pid != 0) ? app : null; 1803 }
478 /**
479 * All of the processes we currently have running organized by pid.
480 * The keys are the pid running the application.
481 *
482 * NOTE: This object is protected by its own lock, NOT the global
483 * activity manager lock!
484 */
485 final SparseArray<ProcessRecord> mPidsSelfLocked
486 = new SparseArray<ProcessRecord>();
:
1809 private final void startProcessLocked(ProcessRecord app,
1810 String hostingType, String hostingNameStr) {
:
1828 try {
1829 int uid = app.info.uid;
1830 int[] gids = null;
1831 try {
1832 gids = mContext.getPackageManager().getPackageGids(
1833 app.info.packageName);
1834 } catch (PackageManager.NameNotFoundException e) {
1835 Slog.w(TAG, "Unable to retrieve gids", e);
1836 }
:
1848 int debugFlags = 0;
1849 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1850 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1851 }
1852 // Run the app in safe mode if its manifest requests so or the
1853 // system is booted in safe mode.
1854 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1855 Zygote.systemInSafeMode == true) {
1856 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1857 }
1858 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1859 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1860 }
1861 if ("1".equals(SystemProperties.get("debug.assert"))) {
1862 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1863 }
1864
1865 // Start the process. It will either succeed and return a result containing
1866 // the PID of the new process, or else throw a RuntimeException.
1867 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
1868 app.processName, uid, uid, gids, debugFlags, null);
→クラス名が "android.app.ActivityThread" の決め打ちであることに注意
:
1908 if (startResult.pid == 0 || startResult.pid == MY_PID) {
1909 // Processes are being emulated with threads.
1910 app.pid = MY_PID;
1911 app.removed = false;
1912 mStartingProcesses.add(app);
1913 } else {
1914 app.pid = startResult.pid;
1915 app.usingWrapper = startResult.usingWrapper;
1916 app.removed = false;
1917 synchronized (mPidsSelfLocked) {
1918 this.mPidsSelfLocked.put(startResult.pid, app);
→当該アプリの ProcessRecord を mPidsSelfLocked テーブルに登録
1919 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1920 msg.obj = app;
1921 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
1922 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
1923 }
1924 }
:
frameworks/base/core/java/android/os/Process.java
236 /**
237 * Start a new process.
238 *
239 * If processes are enabled, a new process is created and the
240 * static main() function of a processClass is executed there.
241 * The process will continue running after this function returns.
242 *
243 * If processes are not enabled, a new thread in the caller's
244 * process is created and main() of processClass called there.
245 *
246 * The niceName parameter, if not an empty string, is a custom name to
247 * give to the process instead of using processClass. This allows you to
248 * make easily identifyable processes even if you are using the same base
249 * processClass to start them.
250 *
251 * @param processClass The class to use as the process's main entry
252 * point.
253 * @param niceName A more readable name to use for the process.
254 * @param uid The user-id under which the process will run.
255 * @param gid The group-id under which the process will run.
256 * @param gids Additional group-ids associated with the process.
257 * @param enableDebugger True if debugging should be enabled for this process.
258 * @param zygoteArgs Additional arguments to supply to the zygote process.
259 *
260 * @return An object that describes the result of the attempt to start the process.
261 * @throws RuntimeException on fatal start failure
262 *
263 * {@hide}
264 */
265 public static final ProcessStartResult start(final String processClass,
266 final String niceName,
267 int uid, int gid, int[] gids,
268 int debugFlags,
269 String[] zygoteArgs)
270 {
271 if (supportsProcesses()) {
272 try {
273 return startViaZygote(processClass, niceName, uid, gid, gids,
274 debugFlags, zygoteArgs);
275 } catch (ZygoteStartFailedEx ex) {
276 Log.e(LOG_TAG,
277 "Starting VM process through Zygote failed");
278 throw new RuntimeException(
279 "Starting VM process through Zygote failed", ex);
280 }
281 } else {
282 // Running in single-process mode
283
284 Runnable runnable = new Runnable() {
285 public void run() {
286 Process.invokeStaticMain(processClass);
287 }
288 };
289
290 // Thread constructors must not be called with null names (see spec).
291 if (niceName != null) {
292 new Thread(runnable, niceName).start();
293 } else {
294 new Thread(runnable).start();
295 }
296 return new ProcessStartResult();
297 }
298 }
478 /** 479 * Starts a new process via the zygote mechanism. 480 * 481 * @param processClass Class name whose static main() to run 482 * @param niceName 'nice' process name to appear in ps 483 * @param uid a POSIX uid that the new process should setuid() to 484 * @param gid a POSIX gid that the new process shuold setgid() to 485 * @param gids null-ok; a list of supplementary group IDs that the 486 * new process should setgroup() to. 487 * @param enableDebugger True if debugging should be enabled for this process. 488 * @param extraArgs Additional arguments to supply to the zygote process. 489 * @return An object that describes the result of the attempt to start the process. 490 * @throws ZygoteStartFailedEx if process start failed for any reason 491 */ 492 private static ProcessStartResult startViaZygote(final String processClass, 493 final String niceName, 494 final int uid, final int gid, 495 final int[] gids, 496 int debugFlags, 497 String[] extraArgs) 498 throws ZygoteStartFailedEx { 499 synchronized(Process.class) { 500 ArrayList<String> argsForZygote = new ArrayList≶String>(); 501 502 // --runtime-init, --setuid=, --setgid=, 503 // and --setgroups= must go first ↓zygote ソケットへ送る電文を編集 504 argsForZygote.add("--runtime-init"); 505 argsForZygote.add("--setuid=" + uid); 506 argsForZygote.add("--setgid=" + gid); 507 if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { 508 argsForZygote.add("--enable-safemode"); 509 } 510 if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) { 511 argsForZygote.add("--enable-debugger"); 512 } 513 if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { 514 argsForZygote.add("--enable-checkjni"); 515 } 516 if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { 517 argsForZygote.add("--enable-assert"); 518 } 519 520 //TODO optionally enable debuger 521 //argsForZygote.add("--enable-debugger"); 522 523 // --setgroups is a comma-separated list 524 if (gids != null && gids.length > 0) { 525 StringBuilder sb = new StringBuilder(); 526 sb.append("--setgroups="); 527 528 int sz = gids.length; 529 for (int i = 0; i < sz; i++) { 530 if (i != 0) { 531 sb.append(','); 532 } 533 sb.append(gids[i]); 534 } 535 536 argsForZygote.add(sb.toString()); 537 } 538 539 if (niceName != null) { 540 argsForZygote.add("--nice-name=" + niceName); 541 } 542 543 argsForZygote.add(processClass); 544 545 if (extraArgs != null) { 546 for (String arg : extraArgs) { 547 argsForZygote.add(arg); 548 } 549 } 550 551 return zygoteSendArgsAndGetResult(argsForZygote); 552 } 553 }
414 /** 415 * Sends an argument list to the zygote process, which starts a new child 416 * and returns the child's pid. Please note: the present implementation 417 * replaces newlines in the argument list with spaces. 418 * @param args argument list 419 * @return An object that describes the result of the attempt to start the process. 420 * @throws ZygoteStartFailedEx if process start failed for any reason 421 */ 422 private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) 423 throws ZygoteStartFailedEx { 424 openZygoteSocketIfNeeded(); 425 426 try { 427 /** 428 * See com.android.internal.os.ZygoteInit.readArgumentList() 429 * Presently the wire format to the zygote process is: 430 * a) a count of arguments (argc, in essence) 431 * b) a number of newline-separated argument strings equal to count 432 * 433 * After the zygote process reads these it will write the pid of 434 * the child or -1 on failure, followed by boolean to 435 * indicate whether a wrapper process was used. 436 */ 437 ↓zygote ソケットへの書き込み 438 sZygoteWriter.write(Integer.toString(args.size())); 439 sZygoteWriter.newLine(); 440 441 int sz = args.size(); 442 for (int i = 0; i < sz; i++) { 443 String arg = args.get(i); 444 if (arg.indexOf('\n') >= 0) { 445 throw new ZygoteStartFailedEx( 446 "embedded newlines not allowed"); 447 } 448 sZygoteWriter.write(arg); 449 sZygoteWriter.newLine(); 450 } 451 452 sZygoteWriter.flush();
3. 要求を受け取った Zygote がプロセスを fork するまで
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
650 /** 651 * Runs the zygote process's select loop. Accepts new connections as 652 * they happen, and reads commands from connections one spawn-request's 653 * worth at a time. 654 * 655 * @throws MethodAndArgsCaller in a child process when a main() should 656 * be executed. 657 */ 658 private static void runSelectLoopMode() throws MethodAndArgsCaller { 659 ArrayList<FileDescriptor> fds = new ArrayList(); 660 ArrayList<ZygoteConnection> peers = new ArrayList(); 661 FileDescriptor[] fdArray = new FileDescriptor[4]; 662 663 fds.add(sServerSocket.getFileDescriptor()); 664 peers.add(null); 665 666 int loopCount = GC_LOOP_COUNT; 667 while (true) { 668 int index; : 687 try { 688 fdArray = fds.toArray(fdArray); 689 index = selectReadable(fdArray); 690 } catch (IOException ex) { 691 throw new RuntimeException("Error in select()", ex); 692 } 693 694 if (index < 0) { 695 throw new RuntimeException("Error in select()"); 696 } else if (index == 0) { 697 ZygoteConnection newPeer = acceptCommandPeer(); 698 peers.add(newPeer); 699 fds.add(newPeer.getFileDesciptor()); 700 } else { 701 boolean done; 702 done = peers.get(index).runOnce(); 703 704 if (done) { 705 peers.remove(index); 706 fds.remove(index); 707 } 708 } 709 } 710 }
195 /** 196 * Waits for and accepts a single command connection. Throws 197 * RuntimeException on failure. 198 */ 199 private static ZygoteConnection acceptCommandPeer() { 200 try { 201 return new ZygoteConnection(sServerSocket.accept()); 202 } catch (IOException ex) { 203 throw new RuntimeException( 204 "IOException during accept()", ex); 205 } 206 }
frameworks/base/core/java/com/android/internal/os/ZygoteConnectionjava
39 /**
40 * A connection that can make spawn requests.
41 */
42 class ZygoteConnection {
43 private static final String TAG = "Zygote";
44
45 /** a prototype instance for a future List.toArray() */
46 private static final int[][] intArray2d = new int[0][0];
47
48 /**
49 * {@link android.net.LocalSocket#setSoTimeout} value for connections.
50 * Effectively, the amount of time a requestor has between the start of
51 * the request and the completed request. The select-loop mode Zygote
52 * doesn't have the logic to return to the select loop in the middle of
53 * a request, so we need to time out here to avoid being denial-of-serviced.
54 */
55 private static final int CONNECTION_TIMEOUT_MILLIS = 1000;
56
57 /** max number of arguments that a connection can specify */
58 private static final int MAX_ZYGOTE_ARGC=1024;
59
60 /**
61 * The command socket.
62 *
63 * mSocket is retained in the child process in "peer wait" mode, so
64 * that it closes when the child process terminates. In other cases,
65 * it is closed in the peer.
66 */
67 private final LocalSocket mSocket;
68 private final DataOutputStream mSocketOutStream;
69 private final BufferedReader mSocketReader;
70 private final Credentials peer;
71
72 /**
73 * A long-lived reference to the original command socket used to launch
74 * this peer. If "peer wait" mode is specified, the process that requested
75 * the new VM instance intends to track the lifetime of the spawned instance
76 * via the command socket. In this case, the command socket is closed
77 * in the Zygote and placed here in the spawned instance so that it will
78 * not be collected and finalized. This field remains null at all times
79 * in the original Zygote process, and in all spawned processes where
80 * "peer-wait" mode was not requested.
81 */
82 private static LocalSocket sPeerWaitSocket = null;
83
84 /**
85 * Constructs instance from connected socket.
86 *
87 * @param socket non-null; connected socket
88 * @throws IOException
89 */
90 ZygoteConnection(LocalSocket socket) throws IOException {
91 mSocket = socket;
92
93 mSocketOutStream
94 = new DataOutputStream(socket.getOutputStream());
95
96 mSocketReader = new BufferedReader(
97 new InputStreamReader(socket.getInputStream()), 256);
98
99 mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
100
101 try {
102 peer = mSocket.getPeerCredentials();
103 } catch (IOException ex) {
104 Log.e(TAG, "Cannot read peer credentials", ex);
105 throw ex;
106 }
107 }
155 /**
156 * Reads one start command from the command socket. If successful,
157 * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
158 * exception is thrown in that child while in the parent process,
159 * the method returns normally. On failure, the child is not
160 * spawned and messages are printed to the log and stderr. Returns
161 * a boolean status value indicating whether an end-of-file on the command
162 * socket has been encountered.
163 *
164 * @return false if command socket should continue to be read from, or
165 * true if an end-of-file has been encountered.
166 * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
167 * method in child process
168 */
169 boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
170
171 String args[];
172 Arguments parsedArgs = null;
173 FileDescriptor[] descriptors;
174
175 try {
176 args = readArgumentList();
177 descriptors = mSocket.getAncillaryFileDescriptors();
178 } catch (IOException ex) {
179 Log.w(TAG, "IOException on command socket " + ex.getMessage());
180 closeSocket();
181 return true;
182 }
183
184 if (args == null) {
185 // EOF reached.
186 closeSocket();
187 return true;
188 }
189
190 /** the stderr of the most recent request, if avail */
191 PrintStream newStderr = null;
192
193 if (descriptors != null && descriptors.length >= 3) {
194 newStderr = new PrintStream(
195 new FileOutputStream(descriptors[2]));
196 }
197
198 int pid = -1;
199 FileDescriptor childPipeFd = null;
200 FileDescriptor serverPipeFd = null;
201
202 try {
203 parsedArgs = new Arguments(args);
204
205 applyUidSecurityPolicy(parsedArgs, peer);
→perr プロセスの uid と電文上の uid, gid 指定の関係をチェック
206 applyRlimitSecurityPolicy(parsedArgs, peer);
207 applyCapabilitiesSecurityPolicy(parsedArgs, peer);
208 applyInvokeWithSecurityPolicy(parsedArgs, peer);
209
210 applyDebuggerSystemProperty(parsedArgs);
211 applyInvokeWithSystemProperty(parsedArgs);
212
213 int[][] rlimits = null;
214
215 if (parsedArgs.rlimits != null) {
216 rlimits = parsedArgs.rlimits.toArray(intArray2d);
217 }
218
219 if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
220 FileDescriptor[] pipeFds = new FileDescriptor[2];
221 ZygoteInit.pipe(pipeFds);
222 childPipeFd = pipeFds[1];
223 serverPipeFd = pipeFds[0];
224 ZygoteInit.setCloseOnExec(serverPipeFd, true);
225 }
226
227 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
228 parsedArgs.gids, parsedArgs.debugFlags, rlimits);
→ネイティブコードでプロセスを fork
229 } catch (IOException ex) {
230 logAndPrintError(newStderr, "Exception creating pipe", ex);
231 } catch (IllegalArgumentException ex) {
232 logAndPrintError(newStderr, "Invalid zygote arguments", ex);
233 } catch (ZygoteSecurityException ex) {
234 logAndPrintError(newStderr,
235 "Zygote security policy prevents request: ", ex);
236 }
237
238 try {
239 if (pid == 0) {
240 // in child
241 ZygoteInit.closeDescriptorQuietly(serverPipeFd);
242 serverPipeFd = null;
243 handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
244
245 // should never get here, the child is expected to either
246 // throw ZygoteInit.MethodAndArgsCaller or exec().
247 return true;
248 } else {
249 // in parent...pid of < 0 means failure
250 ZygoteInit.closeDescriptorQuietly(childPipeFd);
251 childPipeFd = null;
252 return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
253 }
254 } finally {
255 ZygoteInit.closeDescriptorQuietly(childPipeFd);
256 ZygoteInit.closeDescriptorQuietly(serverPipeFd);
257 }
258 }
558 /** 559 * Applies zygote security policy per bugs #875058 and #1082165. 560 * Based on the credentials of the process issuing a zygote command: 561 * 562 * - uid 0 (root) may specify any uid, gid, and setgroups() list 563 * - uid 1000 (Process.SYSTEM_UID) may specify any uid > 1000 in normal 564 * operation. It may also specify any gid and setgroups() list it chooses. 565 * In factory test mode, it may specify any UID. 566 * - Any other uid may not specify any uid, gid, or setgroups list. The 567 * uid and gid will be inherited from the requesting process. 569 * 570 * @param args non-null; zygote spawner arguments 571 * @param peer non-null; peer credentials 572 * @throws ZygoteSecurityException 573 */ 574 private static void applyUidSecurityPolicy(Arguments args, Credentials peer) 575 throws ZygoteSecurityException { 576 577 int peerUid = peer.getUid(); 578 579 if (peerUid == 0) { 580 // Root can do what it wants 581 } else if (peerUid == Process.SYSTEM_UID ) { 582 // System UID is restricted, except in factory test mode 583 String factoryTest = SystemProperties.get("ro.factorytest"); 584 boolean uidRestricted; 585 586 /* In normal operation, SYSTEM_UID can only specify a restricted 587 * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid. 588 */ 589 uidRestricted 590 = !(factoryTest.equals("1") || factoryTest.equals("2")); 591 592 if (uidRestricted 593 && args.uidSpecified && (args.uid < Process.SYSTEM_UID)) { 594 throw new ZygoteSecurityException( 595 "System UID may not launch process with UID < " 596 + Process.SYSTEM_UID); 597 } 598 } else { 599 // Everything else 600 if (args.uidSpecified || args.gidSpecified 601 || args.gids != null) { 602 throw new ZygoteSecurityException( 603 "App UIDs may not specify uid's or gid's"); 604 } → peer プロセスの uid が root でも system でもない場合は 電文に uid, gid の指定があってはならない。 605 } 606 607 // If not otherwise specified, uid and gid are inherited from peer 608 if (!args.uidSpecified) { 609 args.uid = peer.getUid(); 610 args.uidSpecified = true; 611 } 612 if (!args.gidSpecified) { 613 args.gid = peer.getGid(); 614 args.gidSpecified = true; 615 } 616 }
4. fork されたプロセスが Activity Manager へ対象アプリ情報を照会するまで
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
760 /** 761 * Handles post-fork setup of child proc, closing sockets as appropriate, 762 * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller 763 * if successful or returning if failed. 764 * 765 * @param parsedArgs non-null; zygote args 766 * @param descriptors null-ok; new file descriptors for stdio if available. 767 * @param pipeFd null-ok; pipe for communication back to Zygote. 768 * @param newStderr null-ok; stream to use for stderr until stdio 769 * is reopened. 770 * 771 * @throws ZygoteInit.MethodAndArgsCaller on success to 772 * trampoline to code that invokes static main. 773 */ 774 private void handleChildProc(Arguments parsedArgs, 775 FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) 776 throws ZygoteInit.MethodAndArgsCaller { : 792 closeSocket(); 793 ZygoteInit.closeServerSocket(); : 814 if (parsedArgs.runtimeInit) { 815 if (parsedArgs.invokeWith != null) { 816 WrapperInit.execApplication(parsedArgs.invokeWith, 817 parsedArgs.niceName, pipeFd, parsedArgs.remainingArgs); 818 } else { 819 RuntimeInit.zygoteInit(parsedArgs.remainingArgs); 820 } 821 } :
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
244 /** 245 * The main function called when started through the zygote process. This 246 * could be unified with main(), if the native code in finishInit() 247 * were rationalized with Zygote startup. 248 * 249 * Current recognized args: 251 * - [--] <start class name> <args> 253 * 254 * @param argv arg strings 255 */ 256 public static final void zygoteInit(String[] argv) 257 throws ZygoteInit.MethodAndArgsCaller { 258 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); 259 260 redirectLogStreams(); 261 262 commonInit(); 263 zygoteInitNative(); 264 265 applicationInit(argv); 266 }
285 private static void applicationInit(String[] argv) 286 throws ZygoteInit.MethodAndArgsCaller { 287 // We want to be fairly aggressive about heap utilization, to avoid 288 // holding on to a lot of memory that isn't needed. 289 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); 290 291 final Arguments args; 292 try { 293 args = new Arguments(argv); 294 } catch (IllegalArgumentException ex) { 295 Slog.e(TAG, ex.getMessage()); 296 // let the process exit 297 return; 298 } 299 300 // Remaining arguments are passed to the start class's static main 301 invokeStaticMain(args.startClass, args.startArgs); 302 }
177 /** 178 * Invokes a static "main(argv[]) method on class "className". 179 * Converts various failing exceptions into RuntimeExceptions, with 180 * the assumption that they will then cause the VM instance to exit. 181 * 182 * @param className Fully-qualified class name 183 * @param argv Argument vector for main() 184 */ 185 private static void invokeStaticMain(String className, String[] argv) 186 throws ZygoteInit.MethodAndArgsCaller { 187 Class cl; 188 189 try { 190 cl = Class.forName(className); 191 } catch (ClassNotFoundException ex) { 192 throw new RuntimeException( 193 "Missing class when invoking static main " + className, 194 ex); 195 } 196 197 Method m; 198 try { 199 m = cl.getMethod("main", new Class[] { String[].class }); 200 } catch (NoSuchMethodException ex) { 201 throw new RuntimeException( 202 "Missing static main on " + className, ex); 203 } catch (SecurityException ex) { 204 throw new RuntimeException( 205 "Problem getting static main on " + className, ex); 206 } 207 208 int modifiers = m.getModifiers(); 209 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { 210 throw new RuntimeException( 211 "Main method is not public and static on " + className); 212 } 213 214 /* 215 * This throw gets caught in ZygoteInit.main(), which responds 216 * by invoking the exception's run() method. This arrangement 217 * clears up all the stack frames that were required in setting 218 * up the process. 219 */ 220 throw new ZygoteInit.MethodAndArgsCaller(m, argv); 221 }
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
563 public static void main(String argv[]) { 564 try { 565 VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024); 566 567 // Start profiling the zygote initialization. 568 SamplingProfilerIntegration.start(); 569 570 registerZygoteSocket(); 571 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, 572 SystemClock.uptimeMillis()); 573 preload(); 574 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, 575 SystemClock.uptimeMillis()); 576 577 // Finish profiling the zygote initialization. 578 SamplingProfilerIntegration.writeZygoteSnapshot(); 579 580 // Do an initial gc to clean up after startup 581 gc(); 582 583 // If requested, start system server directly from Zygote 584 if (argv.length != 2) { 585 throw new RuntimeException(argv[0] + USAGE_STRING); 586 } 587 588 if (argv[1].equals("start-system-server")) { 589 startSystemServer(); 590 } else if (!argv[1].equals("")) { 591 throw new RuntimeException(argv[0] + USAGE_STRING); 592 } 593 594 Log.i(TAG, "Accepting command socket connections"); 595 596 if (ZYGOTE_FORK_MODE) { 597 runForkMode(); 598 } else { 599 runSelectLoopMode(); 600 } 601 602 closeServerSocket(); 603 } catch (MethodAndArgsCaller caller) { 604 caller.run(); 605 } catch (RuntimeException ex) { 606 Log.e(TAG, "Zygote died with exception", ex); 607 closeServerSocket(); 608 throw ex; 609 } 610 }
frameworks/base/core/java/android/app/ActivityThread.java
3665 public static final void main(String[] args) { 3666 SamplingProfilerIntegration.start(); 3667 3668 Process.setArgV0("<pre-initialized>"); 3669 3670 Looper.prepareMainLooper(); 3671 if (sMainThreadHandler == null) { 3672 sMainThreadHandler = new Handler(); 3673 } 3674 3675 ActivityThread thread = new ActivityThread(); 3676 thread.attach(false); →現プロセスに所定のアプリのコードをロードし実行する 3677 3678 if (false) { 3679 Looper.myLooper().setMessageLogging(new 3680 LogPrinter(Log.DEBUG, "ActivityThread")); 3681 } 3682 3683 Looper.loop(); 3684 3685 if (Process.supportsProcesses()) { 3686 throw new RuntimeException("Main thread loop unexpectedly exited"); 3687 } 3688 3689 thread.detach(); 3690 String name = (thread.mInitialApplication != null) 3691 ? thread.mInitialApplication.getPackageName() 3692 : "<unknown>"; 3693 Slog.i(TAG, "Main thread of " + name + " is now exiting"); 3694 } 3695 }
109 /**
110 * This manages the execution of the main thread in an
111 * application process, scheduling and executing activities,
112 * broadcasts, and other operations on it as the activity
113 * manager requests.
114 *
116 */
117 public final class ActivityThread {
118 static final String TAG = "ActivityThread";
:
137 final ApplicationThread mAppThread = new ApplicationThread();
:
3590 private final void attach(boolean system) {
3591 sThreadLocal.set(this);
3592 mSystemThread = system;
3593 if (!system) {
3594 ViewRoot.addFirstDrawHandler(new Runnable() {
3595 public void run() {
3596 ensureJitEnabled();
3597 }
3598 });
3599 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
3600 RuntimeInit.setApplicationObject(mAppThread.asBinder());
3601 IActivityManager mgr = ActivityManagerNative.getDefault();
3602 try {
3603 mgr.attachApplication(mAppThread);
→ 本プロセス用のアプリの情報を Activity Manager に要求
3604 } catch (RemoteException ex) {
3605 }
3606 }
:
5. Activity Manager が新規プロセスに起動対象アプリ情報を渡すまで
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
3638 public final void attachApplication(IApplicationThread thread) { 3639 synchronized (this) { 3640 int callingPid = Binder.getCallingPid(); 3641 final long origId = Binder.clearCallingIdentity(); 3642 attachApplicationLocked(thread, callingPid); 3643 Binder.restoreCallingIdentity(origId); 3644 } 3645 }
143 public final class ActivityManagerService extends ActivityManagerNative
144 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
145 static final String TAG = "ActivityManager";
146 static final boolean DEBUG = false;
:
389 static final int MY_PID = Process.myPid();
:
478 /**
479 * All of the processes we currently have running organized by pid.
480 * The keys are the pid running the application.
481 *
482 * NOTE: This object is protected by its own lock, NOT the global
483 * activity manager lock!
484 */
485 final SparseArray<ProcessRecord> mPidsSelfLocked
486 = new SparseArray<ProcessRecord>();
:
3417 private final boolean attachApplicationLocked(IApplicationThread thread,
3418 int pid) {
3419
3420 // Find the application record that is being attached... either via
3421 // the pid if we are running in multiple processes, or just pull the
3422 // next app record if we are emulating process with anonymous threads.
3423 ProcessRecord app;
3424 if (pid != MY_PID && pid >= 0) {
3425 synchronized (mPidsSelfLocked) {
3426 app = mPidsSelfLocked.get(pid);
→mPidsSelfLocked テーブルに登録済みの当該 ProcessRecord を取得
3427 }
3428 } else if (mStartingProcesses.size() > 0) {
3429 app = mStartingProcesses.remove(0);
3430 app.setPid(pid);
3431 } else {
3432 app = null;
3433 }
3434
3435 if (app == null) {
3436 Slog.w(TAG, "No pending application record for pid " + pid
3437 + " (IApplicationThread " + thread + "); dropping process");
3438 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
3439 if (pid > 0 && pid != MY_PID) {
3440 Process.killProcess(pid);
3441 } else {
3442 try {
3443 thread.scheduleExit();
3444 } catch (Exception e) {
3445 // Ignore exceptions.
3446 }
3447 }
3448 return false;
3449 }
:
3457 // Tell the process all about itself.
3458
3459 if (localLOGV) Slog.v(
3460 TAG, "Binding process pid " + pid + " to record " + app);
3461
3462 String processName = app.processName;
3463 try {
3464 thread.asBinder().linkToDeath(new AppDeathRecipient(
3465 app, pid, thread), 0);
3466 } catch (RemoteException e) {
3467 app.resetPackageList();
3468 startProcessLocked(app, "link fail", processName);
3469 return false;
3470 }
:
3474 app.thread = thread;
3475 app.curAdj = app.setAdj = -100;
3476 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3477 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
3478 app.forcingToForeground = null;
3479 app.foregroundServices = false;
3480 app.debugging = false;
:
3484 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
3485 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
:
3522 thread.bindApplication(processName, app.instrumentationInfo != null
3523 ? app.instrumentationInfo : app.info, providers,
3524 app.instrumentationClass, app.instrumentationProfileFile,
3525 app.instrumentationArguments, app.instrumentationWatcher, testMode,
3526 isRestrictedBackupMode || !normalMode,
3527 mConfiguration, getCommonServicesLocked());
3528 updateLruProcessLocked(app, false, true);
3529 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
3530 } catch (Exception e) {
:
6. 新プロセスが Activity Manager からの情報をもとにアプリを起動するまで
frameworks/base/core/java/android/app/ActivityThread.java
367 private final class ApplicationThread extends ApplicationThreadNative {
:
535 public final void bindApplication(String processName,
536 ApplicationInfo appInfo, List<ProviderInfo> providers,
537 ComponentName instrumentationName, String profileFile,
538 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
539 int debugMode, boolean isRestrictedBackupMode, Configuration config,
540 Map<String, IBinder> services) {
541
542 if (services != null) {
543 // Setup the service cache in the ServiceManager
544 ServiceManager.initServiceCache(services);
545 }
546
547 AppBindData data = new AppBindData();
548 data.processName = processName;
549 data.appInfo = appInfo;
550 data.providers = providers;
551 data.instrumentationName = instrumentationName;
552 data.profileFile = profileFile;
553 data.instrumentationArgs = instrumentationArgs;
554 data.instrumentationWatcher = instrumentationWatcher;
555 data.debugMode = debugMode;
556 data.restrictedBackupMode = isRestrictedBackupMode;
557 data.config = config;
558 queueOrSendMessage(H.BIND_APPLICATION, data);
559 }
:
323 private static final class AppBindData {
324 LoadedApk info;
325 String processName;
326 ApplicationInfo appInfo;
327 List<ProviderInfo> providers;
328 ComponentName instrumentationName;
329 String profileFile;
330 Bundle instrumentationArgs;
331 IInstrumentationWatcher instrumentationWatcher;
332 int debugMode;
333 boolean restrictedBackupMode;
334 Configuration config;
335 boolean handlingProfiling;
336 public String toString() {
337 return "AppBindData{appInfo=" + appInfo + "}";
338 }
339 }
1504 // if the thread hasn't started yet, we don't have the handler, so just 1505 // save the messages until we're ready. 1506 private final void queueOrSendMessage(int what, Object obj) { 1507 queueOrSendMessage(what, obj, 0, 0); 1508 } 1514 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { 1515 synchronized (this) { 1516 if (DEBUG_MESSAGES) Slog.v( 1517 TAG, "SCHEDULE " + what + " " + mH.codeToString(what) 1518 + ": " + arg1 + " / " + obj); 1519 Message msg = Message.obtain(); 1520 msg.what = what; 1521 msg.obj = obj; 1522 msg.arg1 = arg1; 1523 msg.arg2 = arg2; 1524 mH.sendMessage(msg); 1525 } 1526 } 923 public void handleMessage(Message msg) { 924 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what); 925 switch (msg.what) { 926 case LAUNCH_ACTIVITY: { 927 ActivityClientRecord r = (ActivityClientRecord)msg.obj; 928 929 r.packageInfo = getPackageInfoNoCheck( 930 r.activityInfo.applicationInfo); 931 handleLaunchActivity(r, null); 932 } break; : 967 case BIND_APPLICATION: 968 AppBindData data = (AppBindData)msg.obj; 969 handleBindApplication(data); 970 break; :
323 private static final class AppBindData { 324 LoadedApk info; 325 String processName; 326 ApplicationInfo appInfo; 327 List<ProviderInfo> providers; 328 ComponentName instrumentationName; 329 String profileFile; 330 Bundle instrumentationArgs; 331 IInstrumentationWatcher instrumentationWatcher; 332 int debugMode; 333 boolean restrictedBackupMode; 334 Configuration config; 335 boolean handlingProfiling; 336 public String toString() { 337 return "AppBindData{appInfo=" + appInfo + "}"; 338 } 339 } : 117 public final class ActivityThread { 118 static final String TAG = "ActivityThread"; : 152 Application mInitialApplication; : 158 Instrumentation mInstrumentation; : 3121 private final void handleBindApplication(AppBindData data) { 3122 mBoundApplication = data; 3123 mConfiguration = new Configuration(data.config); : 3149 data.info = getPackageInfoNoCheck(data.appInfo); : 3255 mInstrumentation = new Instrumentation(); : 3258 // If the app is being launched for full backup or restore, bring it up in 3259 // a restricted environment with the base application class. 3260 Application app = data.info.makeApplication(data.restrictedBackupMode, null); 3261 mInitialApplication = app; 3262 3263 List<ProviderInfo> providers = data.providers; 3264 if (providers != null) { 3265 installContentProviders(app, providers); 3266 // For process that contain content providers, we want to 3267 // ensure that the JIT is enabled "at some point". 3268 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); 3269 } 3270 3271 try { 3272 mInstrumentation.callApplicationOnCreate(app); 3273 } catch (Exception e) { 3274 if (!mInstrumentation.onException(app, e)) { 3275 throw new RuntimeException( 3276 "Unable to create application " + app.getClass().getName() 3277 + ": " + e.toString(), e); 3278 } 3279 } 3280 }
frameworks/base/core/java/android/app/LoadedApk.java
62 /** 63 * Local state maintained about a currently loaded .apk. 65 */ 66 final class LoadedApk { : 68 private final ActivityThread mActivityThread; 69 private final ApplicationInfo mApplicationInfo; : 82 private Application mApplication; : 100 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, 101 ActivityThread mainThread, ClassLoader baseLoader, 102 boolean securityViolation, boolean includeCode) { 103 mActivityThread = activityThread; 104 mApplicationInfo = aInfo; 105 mPackageName = aInfo.packageName; : 444 public Application makeApplication(boolean forceDefaultAppClass, 445 Instrumentation instrumentation) { 446 if (mApplication != null) { 447 return mApplication; 448 } 449 450 Application app = null; 451 452 String appClass = mApplicationInfo.className; 453 if (forceDefaultAppClass || (appClass == null)) { 454 appClass = "android.app.Application"; 455 } 456 457 try { 458 java.lang.ClassLoader cl = getClassLoader(); 459 ContextImpl appContext = new ContextImpl(); 460 appContext.init(this, null, mActivityThread); 461 app = mActivityThread.mInstrumentation.newApplication( 462 cl, appClass, appContext); 463 appContext.setOuterContext(app); 464 } catch (Exception e) { 465 if (!mActivityThread.mInstrumentation.onException(app, e)) { 466 throw new RuntimeException( 467 "Unable to instantiate application " + appClass 468 + ": " + e.toString(), e); 469 } 470 } 471 mActivityThread.mAllApplications.add(app); 472 mApplication = app; :
frameworks/base/core/java/android/app/Instrumentation.java
928 /**
929 * Perform instantiation of the process's {@link Application} object. The
930 * default implementation provides the normal system behavior.
931 *
932 * @param cl The ClassLoader with which to instantiate the object.
933 * @param className The name of the class implementing the Application
934 * object.
935 * @param context The context to initialize the application with
936 *
937 * @return The newly instantiated Application object.
938 */
939 public Application newApplication(ClassLoader cl, String className, Context context)
940 throws InstantiationException, IllegalAccessException,
941 ClassNotFoundException {
942 return newApplication(cl.loadClass(className), context);
943 }
944
945 /**
946 * Perform instantiation of the process's {@link Application} object. The
947 * default implementation provides the normal system behavior.
948 *
949 * @param clazz The class used to create an Application object from.
950 * @param context The context to initialize the application with
951 *
952 * @return The newly instantiated Application object.
953 */
954 static public Application newApplication(Class clazz, Context context)
955 throws InstantiationException, IllegalAccessException,
956 ClassNotFoundException {
957 Application app = (Application)clazz.newInstance(); (→new クラス();)
958 app.attach(context);
959 return app;
960 }
962 /**
963 * Perform calling of the application's {@link Application#onCreate}
964 * method. The default implementation simply calls through to that method.
965 *
966 * @param app The application being created.
967 */
968 public void callApplicationOnCreate(Application app) {
969 app.onCreate(); →対象 Activity の onCreate() を実行
970 }
(tanabe)
