bindService流程四

139 阅读2分钟

之前已经分析完在同app进程中bindService的过程。今天继续分析在新进程中bindService的流程。之前的分析可以参考juejin.cn/post/710270…

接着第二篇最后的分析 ActiveServices#bringUpServiceLocked 这里面的启动新进程来分析bindService

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        .......
        
        // 进程未启动
        if (app == null && !permissionsReviewRequired) {
            // step3.3 启动进程
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                return msg;
            }
        }
        return null;
    }


通过mAm.startProcessLocked 启动新的进程,创建新进程涉及到Zygote服务,这边暂时不讨论,可以参考老罗的博客,在进程创建之后回调到ActivityThread的main方法。我们从这边开始分析。 ActivityThread#main

public static void main(String[] args) {

       Looper.prepareMainLooper();
       // 创建ActivityThread
       ActivityThread thread = new ActivityThread();
       // 调用ActivityThread的attach
       thread.attach(false, startSeq);

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

       // 启动loop
       Looper.loop();
   }

这边thread.attach(false, startSeq);会告诉ams进程创建成功,将applicationThread给ams。

ActivityThread#attach

private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        ......
        if (!system) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
                // 通知ams进程创建好了
                mgr.attachApplication(mAppThread, startSeq);
            } 
        }
        ......
    }

调用ams的attachApplication

ActivityManangerService#attachApplication

public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
}

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {

        ProcessRecord app;
        long startTime = SystemClock.uptimeMillis();
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }
        ......
        
            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
            app.compat = compatibilityInfoForPackageLocked(appInfo);
          
            thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            }

        // See if the top visible activity is waiting to run in this process...
        // 检查是否有activity等待此进程运行
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } 
        }

        // Find any services that should be running in this process...
        // 检查是否有service等待此进程运行
        if (!badApp) {
            try {
                // step1 检查service 
                didSomething |= mServices.attachApplicationLocked(app, processName);
            } 
        }
        ......

        return true;
    }


ams会先调用bindApplication创建application。下面会先检查是否有activity等待此进程运行,然后检查是否有service等待此进程运行,所以activity的优先级比service的高点。

ActiveServices#attachApplicationLocked

 boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        ......
        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i = 0; i < mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    // 遍历mPendingServices,查找响应的service
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
                    // 启动service
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                    
                }
            } 
            ......
        }
        return didSomething;
    }

遍历mPendingServices查找对应的ServiceRecord。前面第二篇最后ActiveServices#bringUpServiceLocked juejin.cn/post/710046… 可以看到如果进程未启动servicerecord会保存到mPendingServices中的。 找到后执行realStartServiceLocked方法。 该方法的流程之前已经分析过了,参考juejin.cn/post/710270…