Framework篇 - 四大组件与进程启动的关系

本文源代码基于 Android 7.0。

一个进程里可以运行多个 app,一个 app 也可以运行在多个进程中,通过配置 Android:process 属性来决定。进程对 Android 来说非常重要,承载着 Android 的四大组件,影响着系统的正常运转。

 

目录:

  1. 四大组件与进程
  2. 进程启动的全过程
  3. 启动过程图

 

1. 四大组件与进程

Activity, Service, ContentProvider, BroadcastReceiver 这四大组件,在启动的过程,当其所承载的进程不存在时需要调用startProcessLocked 先创建进程。

 

  • 1.1 Activity

启动 Activity 过程:调用 startActivity,该方法经过层层调用,最终会调用 ActivityStackSupervisor.startSpecificActivityLocked() ,当 activity 所属进程还没启动的情况下,则需要创建相应的进程。

/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 获取 ProcessRecord
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        if (app != null && app.thread != null) {
            // 进程已创建
            return;
        }
        // 进程没创建,去创建进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

代码中的 mService 为 ActivityManagerService。

 

  • 1.2 Service

启动服务过程:调用 startService,该方法经过层层调用,最终会调用 ActiveServices.bringUpServiceLocked(),
当 Service 进程没有启动的情况 (app==null),则需要创建相应的进程。

/base/services/core/java/com/android/server/am/ActiveServices.java

private final String bringUpServiceLocked(...){
    ...
    ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
    if (app == null) {
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                "service", r.name, false, isolated, false)) == null) {
            ...
        }
    }
    ...
}

mAm 为 ActivityManagerService。

 

  • 1.3 ContentProvider

ContentProvider 处理过程:调用 ContentResolver.query() 该方法经过层层调用,最终会调用到 AcitivtyManagerService.getContentProviderImpl(),当 ContentProvider 所对应进程不存在,则需要创建新进程。

/base/services/core/java/com/android/server/am/ActivityManagerService.java

private final ContentProviderHolder getContentProviderImpl(...) {
    ...
    ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false);
    if (proc != null && proc.thread != null) {
        ...  //进程已创建
    } else {
        proc = startProcessLocked(cpi.processName,
                    cpr.appInfo, false, 0, "content provider",
                    new ComponentName(cpi.applicationInfo.packageName,cpi.name),
                    false, false, false);
    }
    ...
}

 

  • 1.4 Broadcast

广播处理过程:调用 sendBroadcast,该方法经过层层调用,最终会调用到 BroadcastQueue.processNextBroadcast(),
当 BroadcastReceiver 所对应的进程尚未启动,则创建相应进程。

/base/services/core/java/com/android/server/am/BroadcastQueue.java

final void processNextBroadcast(boolean fromMsg) {
    ...
    ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
        info.activityInfo.applicationInfo.uid, false);
    if (app != null && app.thread != null) {
        ...  //进程已创建
        return
    }

    if ((r.curApp=mService.startProcessLocked(targetProcess,
            info.activityInfo.applicationInfo, true,
            r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
            "broadcast", r.curComponent,
            (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                    == null) {
        ...
    }
    ...
}

mService 为 ActivityManagerService。

 

  • 1.5 启动进程

/base/services/core/java/com/android/server/am/ActivityManagerService.java

四大组件所在应用首次启动时,会调用 startProcessLocked()。

    /**
     * 在ActivityManagerService.java 启动进程有4个同名不同参数的重载方法StartProcessLocked
     */
    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 */);
    }

    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    }

    private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
        startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
                null /* entryPoint */, null /* entryPointArgs */);
    }

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        //...
    }

 

  • 1.6 进程创建触发时机

大多数情况下,app 都是单进程架构,对于多进程架构的 app 一般是通过在 AndroidManifest.xml 中 android:process 属性来实现的:

  • 当 android:process 属性值以 ":" 开头,则代表进程是私有的,只有该 app 可以使用,其他应用无法访问。
  • 当 android:process 属性值不以 ":" 开头,则代表的是全局型进程,但是这种情况需要注意的是进程名必须包含 "." 字符。

/base/core/java/android/content/pm/PackageParser.java

PackageParser.java 来解析 AndroidManiefst.xml 过程就明白进程名的命名要求:

    private static String buildCompoundName(String pkg,
            CharSequence procSeq, String type, String[] outError) {
        String proc = procSeq.toString();
        char c = proc.charAt(0);
        if (pkg != null && c == ':') {
            if (proc.length() < 2) {
                outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
                        + ": must be at least two characters";
                return null;
            }
            String subName = proc.substring(1);
            String nameError = validateName(subName, false, false);
            if (nameError != null) {
                outError[0] = "Invalid " + type + " name " + proc + " in package "
                        + pkg + ": " + nameError;
                return null;
            }
            return (pkg + proc).intern();
        }
        String nameError = validateName(proc, true, false);
        if (nameError != null && !"system".equals(proc)) {
            outError[0] = "Invalid " + type + " name " + proc + " in package "
                    + pkg + ": " + nameError;
            return null;
        }
        return proc.intern();
    }

单进程 App:

  • 对于这种情况,那么 app 首次启动某个组件时,比如通过调用 startActivity 来启动某个 app,则先会触发创建该 app 进程,然后再启动该 Activity。此时该 app 进程已创建,那么后续再该 app 中内部启动同一个 activity 或者其他组件,则都不会再创建新进程 (除非该 app 进程被系统所杀掉)。

多进程 App:

  • 对于这种情况,那么每个配置过 android:process 属性的组件的首次启动,则都分别需要创建进程。再次启动同一个activity,则不会再创建新进程 (除非该 app 进程被系统所杀掉),但如果启动的是其他组件,则还需要再次判断其所对应的进程是否存在。

 

  • 1.7 小结

Activity,Service,ContentProvider,BroadcastReceiver 这四大组件在启动时,当所承载的进程不存在时,包括多进程的情况,则都需要创建。进程的创建过程交由系统进程 system_server 来完成的。

systemserver 进程中调用 startProcessLocked 方法,该方法最终通过 socket 方式,将需要创建新进程的消息告知 Zygote 进程,并阻塞等待 Socket 返回新创建进程的 pid。Zygote 进程接收到 systemserver 发送过来的消息,则通过 fork 的方法,将zygote 自身进程复制生成新的进程,并将 ActivityThread 相关的资源加载到新进程 app process,这个进程可能是用于承载activity 等组件。

创建完新进程后 fork 返回两次,在新进程 app process 向 servicemanager 查询 systemserver 进程中 Binder 服务端 ActivityManagerSerivce,获取相对应的 Client 端,也就是 ActivityManagerProxy。有了这一对 Binder c/s 对,那么 app process便可以通过 Binder 向跨进程 systemserver 发送请求,即 attachApplication()。

systemserver 进程接收到相应 Binder 操作后,经过多次调用,利用 ApplicationThreadProxy 向 app process 发送 Binder 请求, 即 bindApplication。systemserver 拥有 ApplicationThreadProxy/ActivityManagerSerivce,每一个新创建的进程都会有一个相应的 ApplicationThreadProxy/ActivityManagerSerivce,从而可以跨进程进行相互通信,这便是进程创建过程的完整生态链。

 

 

2. 进程启动的全过程

从 ActivityManagerService.startProcessLocked() 开始。

 

  • 2.1 ActivityManagerService.startProcessLocked()

/base/services/core/java/com/android/server/am/ActivityManagerService.java

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, 
String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, 
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    if (!isolated) {
        //根据进程名和uid检查相应的ProcessRecord
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);

        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
            // 如果当前处于后台进程,检查当前进程是否处于bad进程列表
            if (mBadProcesses.get(info.processName, info.uid) != null) {
                return null;
            }
        } else {
            // 当用户明确地启动进程,则清空crash次数,以保证其不处于bad进程直到下次再弹出crash对话框。
            mProcessCrashTimes.remove(info.processName, info.uid);
            if (mBadProcesses.get(info.processName, info.uid) != null) {
                mBadProcesses.remove(info.processName, info.uid);
                if (app != null) {
                    app.bad = false;
                }
            }
        }
    } else {
        // 对于孤立进程,无法再利用已存在的进程
        app = null;
    }

    // 当存在ProcessRecord,且已分配pid(正在启动或者已经启动),
    // 且caller并不认为该进程已死亡或者没有thread对象attached到该进程.则不应该清理该进程
    if (app != null && app.pid > 0) {
        if (!knownToBeDead || app.thread == null) {
            //如果这是进程中新package,则添加到列表
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            return app;
        }
        //当ProcessRecord已经被attached到先前的一个进程,则杀死并清理该进程
        killProcessGroup(app.info.uid, app.pid);
        handleAppDiedLocked(app, true, true);
    }

    String hostingNameStr = hostingName != null? hostingName.flattenToShortString() : null;
    if (app == null) {
        // 创建新的Process Record对象
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) {
            return null;
        }
        app.crashHandler = crashHandler;
    } else {
        // 如果这是进程中新package,则添加到列表
        app.addPackage(info.packageName, info.versionCode, mProcessStats);
    }
    // 当系统未准备完毕,则将当前进程加入到mProcessesOnHold
    if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) {
        if (!mProcessesOnHold.contains(app)) {
            mProcessesOnHold.add(app);
        }
        return app;
    }
    // 启动进程
    startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    return (app.pid != 0) ? app : null;
}
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride,
 String entryPoint, String[] entryPointArgs) {
    long startTime = SystemClock.elapsedRealtime();
    //当app的pid大于0且不是当前进程的pid,则从mPidsSelfLocked中移除该app.pid
    if (app.pid > 0 && app.pid != MY_PID) {
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        app.setPid(0);
    }
    //从mProcessesOnHold移除该app
    mProcessesOnHold.remove(app);
    updateCpuStats(); //更新cpu统计信息
    try {
        try {
            if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) {
                // 当前package已被冻结,则抛出异常
                throw new RuntimeException("Package " + app.info.packageName + " is frozen!");
            }
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
        if (!app.isolated) {
            int[] permGids = null;
            try {
                //通过Package Manager获取gids
                final IPackageManager pm = AppGlobals.getPackageManager();
                permGids = pm.getPackageGids(app.info.packageName, app.userId);
                MountServiceInternal mountServiceInternal = LocalServices.getService(
                        MountServiceInternal.class);
                mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            // 添加共享app和gids,用于app直接共享资源
            if (ArrayUtils.isEmpty(permGids)) {
                gids = new int[2];
            } else {
                gids = new int[permGids.length + 2];
                System.arraycopy(permGids, 0, gids, 2, permGids.length);
            }
            gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
            gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
        }

        //根据不同参数,设置相应的debugFlags
        ...

        app.gids = gids;
        app.requiredAbi = requiredAbi;
        app.instructionSet = instructionSet;

        boolean isActivityProcess = (entryPoint == null);
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        // 请求Zygote创建新进程[见3.3]
        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);

        ...
        if (app.persistent) {
            Watchdog.getInstance().processStarted(app.processName, startResult.pid);
        }
        //重置ProcessRecord的成员变量
        app.setPid(startResult.pid);
        app.usingWrapper = startResult.usingWrapper;
        app.removed = false;
        app.killed = false;
        app.killedByAm = false;

        // 将新创建的进程加入到mPidsSelfLocked
        synchronized (mPidsSelfLocked) {
            this.mPidsSelfLocked.put(startResult.pid, app);
            if (isActivityProcess) {
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                //延迟发送消息PROC_START_TIMEOUT_MSG
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
        }
    } catch (RuntimeException e) {
        app.setPid(0); //进程创建失败,则重置pid
    }
}

根据不同参数,设置相应的 debugFlags,比如在 AndroidManifest.xml 中设置 androidd:debuggable 为 true,代表 app 运行在debug 模式,则增加 debugger 标识以及开启 JNI check 功能,调用 Process.start 来创建新进程。

 

  • 2.2 Process.start()

/base/core/java/android/os/Process

    public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }


    private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            ArrayList<String> argsForZygote = new ArrayList<String>();

            // --runtime-args, --setuid=, --setgid=,
            // and --setgroups= must go first
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
                argsForZygote.add("--enable-jni-logging");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
                argsForZygote.add("--enable-safemode");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
                argsForZygote.add("--enable-debugger");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
                argsForZygote.add("--enable-checkjni");
            }
            if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
                argsForZygote.add("--generate-debug-info");
            }
            if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {
                argsForZygote.add("--always-jit");
            }
            if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
                argsForZygote.add("--native-debuggable");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                argsForZygote.add("--enable-assert");
            }
            if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
                argsForZygote.add("--mount-external-default");
            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
                argsForZygote.add("--mount-external-read");
            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
                argsForZygote.add("--mount-external-write");
            }
            argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

            //TODO optionally enable debuger
            //argsForZygote.add("--enable-debugger");

            // --setgroups is a comma-separated list
            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }

            if (niceName != null) {
                argsForZygote.add("--nice-name=" + niceName);
            }

            if (seInfo != null) {
                argsForZygote.add("--seinfo=" + seInfo);
            }

            if (instructionSet != null) {
                argsForZygote.add("--instruction-set=" + instructionSet);
            }

            if (appDataDir != null) {
                argsForZygote.add("--app-data-dir=" + appDataDir);
            }

            argsForZygote.add(processClass);

            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }

            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            /**
             * See com.android.internal.os.ZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();

            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }


Process.start() 是通过 socket 通信告知 Zygote 创建 fork 子进程,这边调用 ZygoteState 来发送消息,ZygoteState 定义如下:

public static class ZygoteState {
        final LocalSocket socket;
        final DataInputStream inputStream;
        final BufferedWriter writer;
        final List<String> abiList;

        boolean mClosed;
        //...
}

创建新进程后将 ActivityThread 类加载到新进程,并调用 ActivityThread.main() 方法。

 

  • 2.3 ActivityThread.main()

/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    //性能统计默认是关闭的
    SamplingProfilerIntegration.start();
    //将当前进程所在userId赋值给sCurrentUser
    Environment.initForCurrentUser();

    EventLogger.setReporter(new EventLoggingReporter());
    AndroidKeyStoreProvider.install();

    //确保可信任的CA证书存放在正确的位置
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");

    //创建主线程的Looper对象, 该Looper是不运行退出
    Looper.prepareMainLooper();

    //创建ActivityThread对象
    ActivityThread thread = new ActivityThread();

    //建立Binder通道
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    // 当设置为true时,可打开消息队列的debug log信息
    if (false) {
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop(); //消息循环运行
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

创建主线程的 Looper 对象:该 Looper 是不运行退出,也就是说主线程的 Looper 是在进程创建完成时自动创建完成,如果子线程也需要创建 handler 通信过程,那么就需要手动创建 Looper 对象,并且每个线程只能创建一次。

创建 ActivityThread 对象:

public final class ActivityThread {
    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
}

该过程会初始化几个很重要的变量:

  • mAppThread = new ApplicationThread()
  • mLooper = Looper.myLooper()
  • mH = new H(),H 继承于 Handler,用于处理组件的生命周期

attach 过程是当前主线程向 system_server 进程通信的过程,将 thread 信息告知 ActivityThreadService。接下来还会进一步说明该过程,sMainThreadHandler 通过 getHandler(),获取的对象便是 mH,这就是主线程的 handler 对象。之后主线程调用Looper.loop(),进入消息循环状态,当没有消息时主线程进入休眠状态,一旦有消息到来则唤醒主线程并执行相关操作。

 

  • 2.4 ActivityThread.attach()

/base/core/java/android/app/ActivityThread.java

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
         // 开启虚拟机的jit即时编译功能
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());

        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        // 获取ActivityManagerProxy对象
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            // 调用基于IActivityManager接口的Binder通道
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
        }

        // 观察是否快接近heap的上限
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
                if (!mSomeActivitiesChanged) {
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
                    mSomeActivitiesChanged = false;
                    try {
                        // 当已用内存超过最大内存的3/4,则请求释放内存空间
                        mgr.releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
                    }
                }
            }
        });
    } else {
        ...
    }
    // 添加dropbox日志到libcore
    DropBox.setReporter(new DropBoxReporter());

    // 添加Config回调接口
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });
}

对于非系统 attach 的处理流程:

  • 创建线程来开启虚拟机的 jit 即时编译。
  • 通过 binder,调用到 ActivityManagerService.attachApplication(),其参数 mAppThread 的数据类型为 ApplicationThread。
  • 观察是否快接近 heap 的上限,当已用内存超过最大内存的3/4,则请求释放内存空间。
  • 添加 dropbox 日志到 libcore。
  • 添加 Config 回调接口。

 

  • 2.5 ActivityManagerService.attachApplication()

/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            // ActivityManagerNative调用attachApplication
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                // 根据pid获取ProcessRecord
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        if (app == null) {
            if (pid > 0 && pid != MY_PID) {
                // ProcessRecord为空,则杀掉该进程
                Process.killProcessQuiet(pid);
            } else {
                try {
                    // 退出新建进程的Looper
                    thread.scheduleExit();
                } catch (Exception e) {
                }
            }
            return false;
        }

        // 还刚进入attach过程,此时thread应该为null, 若不为null则表示该app附到上一个进程,则立刻清空
        if (app.thread != null) {
            handleAppDiedLocked(app, true, true);
        }
        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;
        }

        // 重置进程信息
        app.makeActive(thread, mProcessStats); // 执行完该语句,则app.thread便不再为空
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.forcingToForeground = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;

        // app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
        }

        if (!normalMode) {
            Slog.i(TAG, "Launching preboot mode app: " + app);
        }

        if (DEBUG_ALL) Slog.v(
            TAG, "New app record " + app
            + " thread=" + thread.asBinder() + " pid=" + pid);
        try {
            // 获取应用appInfo
            ApplicationInfo appInfo = app.instrumentationInfo != null
                    ? app.instrumentationInfo : app.info;
            // 绑定应用
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            // 更新进程LRU队列
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            app.resetPackageList(mProcessStats);
            app.unlinkDeathRecipient();
            // 每当bind操作失败,则重启启动进程, 此处有可能会导致进程无限重启
            startProcessLocked(app, "bind fail", processName);
            return false;
        }
        //...
        if (badApp) {
            // 杀掉bad应用
            app.kill("error during init", true);
            handleAppDiedLocked(app, false, true);
            return false;
        }

        if (!didSomething) {
            // 更新adj的值
            updateOomAdjLocked();
        }

        return true;
    }
  • 根据 pid 从 mPidsSelfLocked 中查询到相应的 ProcessRecord 对象 app。
  • 当 app==null,意味着本次创建的进程不存在,则直接返回。
  • 还刚进入 attach 过程,此时 thread 应该为 null,若不为 null 则表示该 app 附到上一个进程,则调用 handleAppDiedLocked 清理。
  • 绑定死亡通知,当进程 pid 死亡时会通过 binder 死亡回调,来通知 system_server 进程死亡的消息。
  • 重置 ProcessRecord 进程信息,此时 app.thread 也赋予了新值,便不再为空。
  • app 进程存在正在启动中的 provider,则超时 10s 后发送 CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG 消息。
  • 调用 thread.bindApplication 绑定应用进程。
  • 处理 Provider,Activity,Service,Broadcast 相应流程。

 

  • 2.6 ApplicationThreadProxy.bindApplication()

最终会通过 Binder 调用到 ApplicationThreadNative.onTransact() 的 BIND_APPLICATION_TRANSACTION 分支。

/base/core/java/android/app/ApplicationThreadNative.java

        case BIND_APPLICATION_TRANSACTION:
        {
            // ...
            HashMap<String, IBinder> services = data.readHashMap(null);
            Bundle coreSettings = data.readBundle();
            bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
                    testWatcher, uiAutomationConnection, testMode, enableBinderTracking,
                    trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,
                    coreSettings);
            return true;
        }

 

  • 2.7 ActivityThread$ApplicationThread.bindApplication()

/base/core/java/android/app/ActivityThread.java

private class ApplicationThread extends ApplicationThreadNative {
    public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                // 将services缓存起来, 减少binder检索服务的次数
                ServiceManager.initServiceCache(services);
            }

            // 发送消息H.SET_CORE_SETTINGS
            setCoreSettings(coreSettings);

            // 初始化AppBindData
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            // ...
            sendMessage(H.BIND_APPLICATION, data);
        }
}

ActivityThread.H 收到消息后,会调用 handleBindApplication():

private class H extends Handler {
                  case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
}

 

  • 2.8 ActivityThread.handleBindApplication()

/base/core/java/android/app/ActivityThread.java

private void handleBindApplication(AppBindData data) {

    mBoundApplication = data;
    mConfiguration = new Configuration(data.config);
    mCompatConfiguration = new Configuration(data.config);
    ...

    //设置进程名, 也就是说进程名是在进程真正创建以后的BIND_APPLICATION过程中才取名
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());

    if (data.persistent) {
        //低内存设备, persistent进程不采用硬件加速绘制,以节省内存使用量
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(false);
        }
    }

    //重置时区
    TimeZone.setDefault(null);
    Locale.setDefault(data.config.locale);

    //更新系统配置
    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    applyCompatConfiguration(mCurDefaultDisplayDpi);

    //获取LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 创建ContextImpl上下文
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (!Process.isIsolated()) {
        final File cacheDir = appContext.getCacheDir();
        if (cacheDir != null) {
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
        }

        //用于存储产生/编译的图形代码
        final File codeCacheDir = appContext.getCodeCacheDir();
        if (codeCacheDir != null) {
            setupGraphicsSupport(data.info, codeCacheDir);
        }
    }
    ...

    //当处于调试模式,则运行应用生成systrace信息
    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    Trace.setAppTracingAllowed(appTracingAllowed);

    //初始化 默认的http代理
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
        Proxy.setHttpProxySystemProperty(proxyInfo);
    }

    if (data.instrumentationName != null) {
        ...
    } else {
        mInstrumentation = new Instrumentation();
    }

    //FLAG_LARGE_HEAP则清除内存增长上限
    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[见小节3.14]
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }

        mInstrumentation.onCreate(data.instrumentationArgs);
        //调用Application.onCreate()回调方法.
        mInstrumentation.callApplicationOnCreate(app);

    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

在 handleBindApplication() 的过程中,会同时设置以下两个值:

  • LoadedApk.mApplication
  • ActivityThread.mInitialApplication

 

2.9 ActivityThread​​​​.getPackageInfoNoCheck()

/base/core/java/android/app/ActivityThread.java

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

    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
            boolean registerPackage) {
        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (differentUser) {
                ref = null;
            } else if (includeCode) {
                ref = mPackages.get(aInfo.packageName);
            } else {
                ref = mResourcePackages.get(aInfo.packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            if (packageInfo == null || (packageInfo.mResources != null
                    && !packageInfo.mResources.getAssets().isUpToDate())) {
           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());
                }

                if (differentUser) {
                } else if (includeCode) {
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                } else {
                    mResourcePackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                }
            }
            return packageInfo;
        }
    }

上面过程为创建 LoadedApk 对象。

 

  • 2.10 LoadedApk.makeApplication()

/base/core/java/android/app/LoadedApk.java

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            // 创建 ContextImpl 对象
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            // 反射创建 Application 对象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        // 设置mApplication对象值
        mApplication = app;

        if (instrumentation != null) {
            try {
                // 回调 Application 的 onCreate() 方法
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }
        return app;
    }

获取 ClassLoader,根据 ActivityThread  创建 ContextImpl,然后调用 mActivityThread.mInstrumentation.newApplication(),传入参数 ClassLoader, "android.app.Application" 和 ContextImpl。

 

  • 2.11 Instrumentation.newApplication() & callApplicationOnCreate()

/base/core/java/android/app/Instrumentation.java

public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, 
IllegalAccessException, ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}

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

 

 

3. 启动过程图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值