【23】Android 应用程序入口探究

目录

前言

Android 框架

Android系统启动流程

        装载机层

内核层

原生API层

框架层(Framework)

应用层

Android应用程序打开流程

重要声明

参考鸣谢


前言

如果你和我一样刚刚接触安卓不久,又恰巧学过其他编程,那么你多半会有个和我一样的疑问缠绕心头:Android 程序的入口到底在哪里?

我们知道,Android开发采用的编程语言是 Java Kotlin,由于目前使用的是 Java ,这里仅说 Java。以往我们写 Java程序都会有一个入口函数main;而我们之前写的 Demo,程序都是从 Activity onCreate( ) 方法中开始执行,那么它就我们Anroid APP程序的入口吗 ?

答案是 否定的

我们都知道我们 Android 应用程序是运行在 Android系统 之上的,即先有 Android系统,才能运行我们的 app

下面我们先看了解下 Android 的整体框架及 Android 系统的启动流程:

Android 框架

Android系统启动流程

装载机层

  • Boot Rom:当手机处于关机状态时,长按开机键开机,会引导芯片开始从固化在 ROM 里的代码开始执行,然后加载引导程序到RAM
  • Boot Loader:启动 Android 系统之前的引导程序,主要是检查 RAM,初始化参数等

内核层

Kernel层指的就是 Android 的 Linux内核层,其启动流程如下:

  • 启动 swapper进程PID = 0),这是系统初始化过程内核创建的第一个进程,用于初始化进程管理,内存管理,加载DisplayCameraBinder等驱动相关工作
  • 启动 kthreadd 进程PID = 2),它会创建内核工作 线程 kworkder,软中断 线程ksoftirqdthermal 等内核守护进程。

       kthreadd 是所有内核进程的鼻祖。

原生API层

这里 Native层 主要包括 init进程PID = 1) 孵化的用户空间的守护进程,HAL 层以及开机动画等。

  • init 进程会孵化出 ueventdlogdhealthdinstalldadbdlmkd 等用户守护进程;
  • init 进度即将启动 ServiceManager(Binder 服务管家),bootanim(开机动画)等重要服务。
  • init 进程孵化出 Zygote进程Zygote进程是 Android 系统第一个 Java 进程(虚拟机进程)。

        Init 是所有用户空间进程的鼻祖。

        Zygote进程是所有 Java 进程的父进程。

框架层(Framework)

Zygote 进程,是由 init 进程通过解析 init.rc 文件后 fork( ) 生成的,它主要包括以下内

  • 加载 ZygoteInit 类,注册 Zygote Socket 服务端套接字
  • 加载虚拟机
  • 提前加载类 preloadClasses
  • 提前加载资源 preloadResouces

System Server 进程,是由 Zygote 进程 fork( ) 而来

  • System Server Zygote 孵化的第一个进程。
  • System Server 负责启动和管理整个 Java framework,包含 ActivityManagerWindowManagerPackageManagerPowerManager 等服务。

Media Server 进程,是由 init 进程 fork( )  而来

负责启动和管理整个 C++ framework,包含 AudioFlingerCamera Service 等服务。

应用层

  • Zygote 孵化进程第的一个 App进程 Launcher进程,也就是我们的桌面进程。
  • Zygote进程 也会创建 BrowserPhoneEmail等应用进程。也就是说所有的应用都是进程由 Zygote 进程 fork() 生成的。而且上层的进程全部由下层的进程进行管理,包括但不限于界面的注册,跳转,消息的传递。

Android应用程序打开流程

重要声明

本次Android源码阅读的版本是 2014-09-06- 索引:棒棒糖 - 5.0.0_r2

为什么不看最新的源码呢,因为资料少..目前还真啃不动

主界面 Launcher 其实也是一个 Activity,它存在击 icon 的事件OnClick()

// 代码节选:
// Launcher.java   --- 2428
    /**
     * Launches the intent referred by the clicked shortcut.
     *
     * @param v The view representing the clicked shortcut.
     */
    public void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is launching, or after the
        // view has detached (it's possible for this to happen if the view is removed mid touch).
        if (v.getWindowToken() == null) {
            return;
        }

        if (!mWorkspace.isFinishedSwitchingState()) {
            return;
        }

        if (v instanceof Workspace) {
            if (mWorkspace.isInOverviewMode()) {
                mWorkspace.exitOverviewMode(true);
            }
            return;
        }

        if (v instanceof CellLayout) {
            if (mWorkspace.isInOverviewMode()) {
                mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true);
            }
        }

        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            onClickAppShortcut(v);
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                onClickFolderIcon(v);
            }
        } else if (v == mAllAppsButton) {
            onClickAllAppsButton(v);
        } else if (tag instanceof AppInfo) {
            startAppShortcutOrInfoActivity(v);
        } else if (tag instanceof LauncherAppWidgetInfo) {
            if (v instanceof PendingAppWidgetHostView) {
                onClickPendingWidget((PendingAppWidgetHostView) v);
            }
        }
    }

OnClick 事件会调用 startAppShortcutOrInfoActivity ()

// 代码节选:
// Launcher.java   --- 2629
private void startAppShortcutOrInfoActivity(View v) {
        Object tag = v.getTag();
        final ShortcutInfo shortcut;
        final Intent intent;
        if (tag instanceof ShortcutInfo) {
            shortcut = (ShortcutInfo) tag;
            intent = shortcut.intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));

        } else if (tag instanceof AppInfo) {
            shortcut = null;
            intent = ((AppInfo) tag).intent;
        } else {
            throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
        }

        boolean success = startActivitySafely(v, intent, tag);
        mStats.recordLaunch(intent, shortcut);

        if (success && v instanceof BubbleTextView) {
            mWaitingForResume = (BubbleTextView) v;
            mWaitingForResume.setStayPressed(true);
        }
    }

这里调用了 startActivitySafely() 并通过 Binder IPC 机制 调用 ActivityManagerService.java 中的 startActivity (Intent)

// 代码节选:
// ActivityManagerService.java   --- 3589
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

ActivityManagerService 会执行如下操作:

  • 通过 PackageManager resolveIntent () 收集这个 intent 对象的指向信息,并将指向信息被存储在一个 intent 对象中。
// 代码节选:
// ActivityManagerService.java   --- 3341
ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
                        intent,
                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                            flags, userId);
  • 通过 grantUriPermissionLocked () 方法来验证用户是否有足够的权限去调用该 intent 对象指向的 Activity.
// 代码节选:
// ActivityManagerService.java   --- 7538
// grantUriPermissionLocked () 在 7388 处
/**
     * @param uri This uri must NOT contain an embedded userId.
     * @param userId The userId in which the uri is to be resolved.
     */
    @Override
    public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
            final int modeFlags, int userId) {
        enforceNotIsolatedCaller("grantUriPermission");
        GrantUri grantUri = new GrantUri(userId, uri, false);
        synchronized(this) {
            final ProcessRecord r = getRecordForAppLocked(caller);
            if (r == null) {
                throw new SecurityException("Unable to find app for caller "
                        + caller
                        + " when granting permission to uri " + grantUri);
            }
            if (targetPkg == null) {
                throw new IllegalArgumentException("null target");
            }
            if (grantUri == null) {
                throw new IllegalArgumentException("null uri");
            }

            Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);

            grantUriPermissionLocked(r.uid, targetPkg, grantUri, modeFlags, null,
                    UserHandle.getUserId(r.uid));
        }
    }
  • 如果有权限,ActivityManagerService 会检查并在新的 task 中启动目标 activity
    这时需要先检查这个进程的 ProcessRecord 是否存在了。(ProcessRecord 是用于描述进程的数据结构对象)
    如果 ProcessRecord null, ActivityManagerService 会创建新的进程来实例化目标 activity.

为了启动 App 并使其 Activity 进入 resumed 状态,需要先使当前运行的 Activity(也就是 Launcher) 进入 Paused 状态

ActivityManagerService 最终调用 overridePendingTransition( ) 执行(未严格验证)

// 代码摘取:
// ActivityManagerService .java  ---- 4700
    @Override
    public void overridePendingTransition(IBinder token, String packageName,
            int enterAnim, int exitAnim) {
        synchronized(this) {
            ActivityRecord self = ActivityRecord.isInStackLocked(token);
            if (self == null) {
                return;
            }

            final long origId = Binder.clearCallingIdentity();

            if (self.state == ActivityState.RESUMED
                    || self.state == ActivityState.PAUSING) {
                mWindowManager.overridePendingAppTransition(packageName,
                        enterAnim, exitAnim, null);
            }

            Binder.restoreCallingIdentity(origId);
        }
    }

之后又通过 Binder 通信 调用到 ApplicationThread 的 schedulePauseActivity( )向本地的消息循环中加入一个 H.PAUSE_ACTIVITY 的消息。

// 代码摘取:
// ApplicationThread.java  ---- 565
        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

之后会通过 Handler 的子类  - H 发送消息,处理消息的逻辑在 ActivityThread.java 的 handleMessage( ) 

// 代码摘取:
// ActivityThread.java  ---- 1269
        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;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //...
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }

最终会调用 Activity performPause () 方法

// 代码摘取:
// Activity.java  ---- 6040
    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

终于出现一个比较熟悉的身影了   onPause( )

之后在 handlePauseActivity ( ) 中调用 ActivityManagerNative.getDefault().activityPaused(token);

// 代码摘取:
// Activitythread.java  ---- 3149
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

通过 Binder 机制调用 ActivityManagerService 中的 activityPaused ( ) 方法,如下:

// 代码摘录:
//ActivityManagerService.java   ---- 6435
    @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

最终调用到 startProcessLocked ( )

该方法用以创建新的进程,通过 socket 通道传递参数给 Zygote 进程。Zygote 孵化自身,并调用 ZygoteInit.main () 方法来实例化 ActivityThread 对象并最终返回新进程的 pid。具体过程如下:

// 代码摘录:
// ActivityManagerService.java   ---- 2947
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

接着会调用startProcessLocked ( )的重载方法:

// 代码摘录:
//ActivityManagerService.java   ---- 3189
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            
            //...

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");
            
            //...

    }

Process.start ( ) 实际上是调用 Zygote fork( ) 一个新的进程,并且在最后会调用 ActivityThread main () 方法。ActivityManagerService 所在的进程和 Zygote 所在的进程通过 Socket 通信,ZygoteInit 中循环侦听 Socket 连接:

// 代码摘录
// ZygoteInit.java    ---- 733
/**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     *
     * @throws MethodAndArgsCaller in a child process when a main() should
     * be executed.
     */
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        FileDescriptor[] fdArray = new FileDescriptor[4];

        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;

            /*
             * Call gc() before we block in select().
             * It's work that has to be done anyway, and it's better
             * to avoid making every child do it.  It will also
             * madvise() any free memory as a side-effect.
             *
             * Don't call it every time, because walking the entire
             * heap is a lot of overhead to free a few hundred bytes.
             */
            if (loopCount <= 0) {
                gc();
                loopCount = GC_LOOP_COUNT;
            } else {
                loopCount--;
            }


            try {
                fdArray = fds.toArray(fdArray);
                index = selectReadable(fdArray);
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }

            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDescriptor());
            } else {
                boolean done;
                done = peers.get(index).runOnce();

                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }

可发现:

一旦建立 ZygoteConnection 即调用 runOnce( )

//代码摘录:
//ZygoteConnection.java    ---- 142
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

            //...

            checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);

        //...

        try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

                // should never get here, the child is expected to either
                // throw ZygoteInit.MethodAndArgsCaller or exec().
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }

            //...
}

我们来看看 forkAndSpecialize ( )

//代码摘录:
//Zygote.java    ---- 87
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
          String instructionSet, String appDataDir) {
        long startTime = SystemClock.elapsedRealtime();
        VM_HOOKS.preFork();
        checkTime(startTime, "Zygote.preFork");
        int pid = nativeForkAndSpecialize(
                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                  instructionSet, appDataDir);
        checkTime(startTime, "Zygote.nativeForkAndSpecialize");
        VM_HOOKS.postForkCommon();
        checkTime(startTime, "Zygote.postForkCommon");
        return pid;
    }

最终会去 fork( ) 进程,在子进程 (即 App 进程) 中执行 handleChildProc ( ) 方法

//代码摘录:
//ZygoteConnection.java    ---- 855

    /**
     * Handles post-fork setup of child proc, closing sockets as appropriate,
     * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
     * if successful or returning if failed.
     *
     * @param parsedArgs non-null; zygote args
     * @param descriptors null-ok; new file descriptors for stdio if available.
     * @param pipeFd null-ok; pipe for communication back to Zygote.
     * @param newStderr null-ok; stream to use for stderr until stdio
     * is reopened.
     *
     * @throws ZygoteInit.MethodAndArgsCaller on success to
     * trampoline to code that invokes static main.
     */
    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {

        /**
         * By the time we get here, the native code has closed the two actual Zygote
         * socket connections, and substituted /dev/null in their place.  The LocalSocket
         * objects still need to be closed properly.
         */

        closeSocket();
        ZygoteInit.closeServerSocket();

        if (descriptors != null) {
            try {
                ZygoteInit.reopenStdio(descriptors[0],
                        descriptors[1], descriptors[2]);

                for (FileDescriptor fd: descriptors) {
                    IoUtils.closeQuietly(fd);
                }
                newStderr = System.err;
            } catch (IOException ex) {
                Log.e(TAG, "Error reopening stdio", ex);
            }
        }

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        if (parsedArgs.runtimeInit) {
            if (parsedArgs.invokeWith != null) {
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        pipeFd, parsedArgs.remainingArgs);
            } else {
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
        } else {
            String className;
            try {
                className = parsedArgs.remainingArgs[0];
            } catch (ArrayIndexOutOfBoundsException ex) {
                logAndPrintError(newStderr,
                        "Missing required class name argument", null);
                return;
            }

            String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
            System.arraycopy(parsedArgs.remainingArgs, 1,
                    mainArgs, 0, mainArgs.length);

            if (parsedArgs.invokeWith != null) {
                WrapperInit.execStandalone(parsedArgs.invokeWith,
                        parsedArgs.classpath, className, mainArgs);
            } else {
                ClassLoader cloader;
                if (parsedArgs.classpath != null) {
                    cloader = new PathClassLoader(parsedArgs.classpath,
                            ClassLoader.getSystemClassLoader());
                } else {
                    cloader = ClassLoader.getSystemClassLoader();
                }

                try {
                    ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
                } catch (RuntimeException ex) {
                    logAndPrintError(newStderr, "Error starting.", ex);
                }
            }
        }
    }

注意到后面调用了 ZygoteInit.invokeStaticMain(cloader, className, mainArgs);

本处即调用 ActivityThread main () 方法

//代码摘录:
//ActivityThread.java    ---- 5184

        public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        //初始化当前UserID
        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        Security.addProvider(new AndroidKeyStoreProvider());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        //设置当前用户CA证书的保存位置
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        //设置进程名
        Process.setArgV0("<pre-initialized>");

        //为主进程创建Looper
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        //发出创建ActivityThread的消息
        thread.attach(false);

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

        AsyncTask.init();

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

        //主线程进入无限循环状态,等待接收消息
        Looper.loop();

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

从这里开始,准备主线程的消息队列,并为 App 创建并配置一个 ActivityThread, 再通过 thread.attach ( ) ActivityThead, ApplicationThread ActivityManagerService 关联起来。

ActivityThread 随后依次调用 Looper.prepareLoop () Looper.loop () 来开启消息循环

ActivityManagerService 通过 Binder 通知 ActivityThread 进行 App 中主线程的调度工作。

ActivityThread main( )逻辑如下:

大佬原图,可点击查看大图(ps:转自  3分钟看懂 Activity 启动流程

参考鸣谢

Where is main() in Android?

Android 应用的真正入口是哪里?Seasoninthesun - 回答(强烈推荐)

Android系统架构开篇(强烈推荐)

3 分钟看懂 Activity 启动流程(强烈推荐)

Android 应用程序进程启动过程(强烈推荐)

Android 应用程序入口源码解析

ActivityThread的main方法究竟做了什么

 

资源下载

    链接    提取码: b2cg 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值