美文网首页
Activity/应用(O/8.0)启动流程(四)创建appcl

Activity/应用(O/8.0)启动流程(四)创建appcl

作者: 小川君 | 来源:发表于2018-11-14 19:40 被阅读0次

    Activity/应用(O/8.0)启动流程(一)
    Activity/应用(O/8.0)启动流程(二)
    Activity/应用(O/8.0)启动流程(三)
    Activity/应用(O/8.0)启动流程(四)

    上一篇我们创建了进程,并在此进程中创建了ActivityThread,我们知道ActivityThread是应用的入口,我们现在就来简单分析一番。

    ActivityThread#main
      public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    
            // Make sure TrustedCertificateStore looks in the right place for CA certificates
            final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
            TrustedCertificateStore.setDefaultUserDirectory(configDir);
    
            Process.setArgV0("<pre-initialized>");
           //  创建一个主线程
            Looper.prepareMainLooper();
          //  创建ActivityThread对象,并调用其attach方法
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            if (false) {
                Looper.myLooper().setMessageLogging(new
                        LogPrinter(Log.DEBUG, "ActivityThread"));
            }
    
            // End of event ActivityThreadMain.
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           //  开启主线程循环
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    ActivityThread#attach
    private void attach(boolean system) {
            sCurrentActivityThread = this;
            mSystemThread = system;
          //  如果当前应用不是系统应用
            if (!system) {
                ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    @Override
                    public void run() {
                        ensureJitEnabled();
                    }
                });
                android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                        UserHandle.myUserId());
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                final IActivityManager mgr = ActivityManager.getService();
                try {
                   调用AMS的attachApplicationLocked将新建的ActivityThread传过去
                    mgr.(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                // Watch for getting close to heap limit.
                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)) {
                            if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                    + " total=" + (runtime.totalMemory()/1024)
                                    + " used=" + (dalvikUsed/1024));
                            mSomeActivitiesChanged = false;
                            try {
                                mgr.releaseSomeActivities(mAppThread);
                            } catch (RemoteException e) {
                                throw e.rethrowFromSystemServer();
                            }
                        }
                    }
                });
            } else {
    //  这个分支就不说了
         
            }
    
          //  ...  这里是window的一些设置,这里不多说
        }
    

    我们将ActivityThread传给了AMS

    AMS#attachApplicationLocked
        private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid) {
    
            // Find the application record that is being attached...  either via
            // the pid if we are running in multiple processes, or just pull the
            // next app record if we are emulating process with anonymous threads.
            ProcessRecord app;
            long startTime = SystemClock.uptimeMillis();
            if (pid != MY_PID && pid >= 0) {
              //  我们在进程创建成功之后会在AMS中保存起来,这里根据pid进行获取
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);
                }
            } else {
                app = null;
            }
    
            if (app == null) {
                Slog.w(TAG, "No pending application record for pid " + pid
                        + " (IApplicationThread " + thread + "); dropping process");
                EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
                if (pid > 0 && pid != MY_PID) {
                    killProcessQuiet(pid);
                    //TODO: killProcessGroup(app.info.uid, pid);
                } else {
                    try { 
                        // 如果进程不存在 执行退出操作,也就是退出应用
                        thread.scheduleExit();
                    } catch (Exception e) {
                        // Ignore exceptions.
                    }
                }
                return false;
            }
    
            // If this application record is still attached to a previous
            // process, clean it up now.
            if (app.thread != null) {
                handleAppDiedLocked(app, true, true);
            }
    
            // Tell the process all about itself.
    
                // .... 代码省略
                //  下面这个循环体检查已经启动过的Application是否有与当前将要启动的一样,如果一致,则设置instr
                if (mActiveInstrumentation.size() > 0 && app.instr == null) {
                    for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) {
                        ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
                        if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
                            if (aInstr.mTargetProcesses.length == 0) {
                                // This is the wildcard mode, where every process brought up for
                                // the target instrumentation should be included.
                                if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
                                    app.instr = aInstr;
                                    aInstr.mRunningProcesses.add(app);
                                }
                            } else {
                                for (String proc : aInstr.mTargetProcesses) {
                                    if (proc.equals(app.processName)) {
                                        app.instr = aInstr;
                                        aInstr.mRunningProcesses.add(app);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
    
                // If we were asked to attach an agent on startup, do so now, before we're binding
                // application code.
                if (agent != null) {
                    thread.attachAgent(agent);
                }
    
                checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
                mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app);
                   // 如果是应用内启动一个其他进程的activity那么就会走下面的if,启动应用的话会走else
                if (app.instr != null) {
                    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);
                } else {
                    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                            null, null, null, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated),
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                }
    
                checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
                updateLruProcessLocked(app, false, null);
                checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
                app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
            } catch (Exception e) {
                // todo: Yikes!  What should we do?  For now we will try to
                // start another process, but that could easily get us in
                // an infinite loop of restarting processes...
                Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
    
                app.resetPackageList(mProcessStats);
                app.unlinkDeathRecipient();
                startProcessLocked(app, "bind fail", processName);
                return false;
            }
    
            // Remove this record from the list of starting applications.
            mPersistentStartingProcesses.remove(app);
            if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                    "Attach application locked removing on hold: " + app);
            mProcessesOnHold.remove(app);
    
            boolean badApp = false;
            boolean didSomething = false;
    
            // See if the top visible activity is waiting to run in this process...
            if (normalMode) {
                try {
                    //  上面是创建appclication,这个方法则是创建activity
                    if (mStackSupervisor.attachApplicationLocked(app)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
    
             // ...  代码省略
    
            return true;
        }
    
    1)创建appclication

    我们先来看bindApplication

    ActivityThread#ApplicationThread#bindApplication:
            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 services, Bundle coreSettings,
                    String buildSerial) {
    
                if (services != null) {
                    // Setup the service cache in the ServiceManager
                    ServiceManager.initServiceCache(services);
                }
    
                setCoreSettings(coreSettings);
    
                AppBindData data = new AppBindData();
                data.processName = processName;
                data.appInfo = appInfo;
                data.providers = providers;
                data.instrumentationName = instrumentationName;
                data.instrumentationArgs = instrumentationArgs;
                data.instrumentationWatcher = instrumentationWatcher;
                data.instrumentationUiAutomationConnection = instrumentationUiConnection;
                data.debugMode = debugMode;
                data.enableBinderTracking = enableBinderTracking;
                data.trackAllocation = trackAllocation;
                data.restrictedBackupMode = isRestrictedBackupMode;
                data.persistent = persistent;
                data.config = config;
                data.compatInfo = compatInfo;
                data.initProfilerInfo = profilerInfo;
                data.buildSerial = buildSerial;
                // 发送一条消息
                sendMessage(H.BIND_APPLICATION, data);
            }
    
     // ActivityThread#handleBindApplication
        private void handleBindApplication(AppBindData data) {
            // Register the UI Thread as a sensitive thread to the runtime.
            VMRuntime.registerSensitiveThread();
    
             // ...  代码省略
    
            // 这里根据data的Applicationinfo创建一个LoadedApk对象,并赋值给data.info
            data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    
            // ....  代码省略
    
            final InstrumentationInfo ii;
           // 如果是启动应用的话,不会走下面的if,如果是应用内启动的话,则会走下面
            if (data.instrumentationName != null) {
                try {
                  // 创建InstrumentationInfo 对象
                    ii = new ApplicationPackageManager(null, getPackageManager())
                            .getInstrumentationInfo(data.instrumentationName, 0);
                } catch (PackageManager.NameNotFoundException e) {
                    throw new RuntimeException(
                            "Unable to find instrumentation info for: " + data.instrumentationName);
                }
    
                mInstrumentationPackageName = ii.packageName;
                mInstrumentationAppDir = ii.sourceDir;
                mInstrumentationSplitAppDirs = ii.splitSourceDirs;
                mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
                mInstrumentedAppDir = data.info.getAppDir();
                mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
                mInstrumentedLibDir = data.info.getLibDir();
            } else {
                ii = null;
            }
           // 根据LoadedApk创建一个ContextImpl对象,也就是我们平常用到的Contenxt,目前里面只有ActivityThread和LoadedApk两个参数值
            final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
            updateLocaleListFromAppContext(appContext,
                    mResourcesManager.getConfiguration().getLocales());
    
            if (!Process.isIsolated()) {
                setupGraphicsSupport(appContext);
            }
    
            // If we use profiles, setup the dex reporter to notify package manager
            // of any relevant dex loads. The idle maintenance job will use the information
            // reported to optimize the loaded dex files.
            // Note that we only need one global reporter per app.
            // Make sure we do this before calling onCreate so that we can capture the
            // complete application startup.
            if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
                BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
            }
    
            // Install the Network Security Config Provider. This must happen before the application
            // code is loaded to prevent issues with instances of TLS objects being created before
            // the provider is installed.
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
            NetworkSecurityConfigProvider.install(appContext);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    
            // Continue loading instrumentation.
             // 上面说过了如果是启动应用的话ii == null,应用内启动的话 ii  != null
            if (ii != null) {
                final ApplicationInfo instrApp = new ApplicationInfo();
                ii.copyTo(instrApp);
                instrApp.initForUser(UserHandle.myUserId());
                final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false); 
              //  这里又创建一次ContextImpl ,不过是为了创建Instrumentation
                final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    
                try {
                     //  反射创建Instrumentation
                    final ClassLoader cl = instrContext.getClassLoader();
                    mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(
                        "Unable to instantiate instrumentation "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
    
                final ComponentName component = new ComponentName(ii.packageName, ii.name);
                // 调用init进行初始化
                mInstrumentation.init(this, instrContext, appContext, component,
                        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
    
                if (mProfiler.profileFile != null && !ii.handleProfiling
                        && mProfiler.profileFd == null) {
                    mProfiler.handlingProfiling = true;
                    final File file = new File(mProfiler.profileFile);
                    file.getParentFile().mkdirs();
                    Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
                }
            } else {
               // 如果是启动应用 则直接new
                mInstrumentation = new Instrumentation();
            }
    
            if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
                dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
            } else {
                // Small heap, clamp to the current growth limit and let the heap release
                // pages after the growth limit to the non growth limit capacity. b/18387825
                dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
            }
    
            // Allow disk access during application and provider setup. This could
            // block processing ordered broadcasts, but later processing would
            // probably end up doing the same disk access.
            Application app;
            final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
            final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
            try {
                // If the app is being launched for full backup or restore, bring it up in
                // a restricted environment with the base application class.
               //  这里通过LoadedApk创建appclication对象
                app = data.info.makeApplication(data.restrictedBackupMode, null);
                mInitialApplication = app;
    
                // don't bring up providers in restricted mode; they may depend on the
                // app's custom Application class
                if (!data.restrictedBackupMode) {
                    if (!ArrayUtils.isEmpty(data.providers)) {
                        installContentProviders(app, data.providers);
                        // For process that contains content providers, we want to
                        // ensure that the JIT is enabled "at some point".
                        mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                    }
                }
    
                // Do this after providers, since instrumentation tests generally start their
                // test thread at this point, and we don't want that racing.
                try {
                  //  这里是个空方法
                    mInstrumentation.onCreate(data.instrumentationArgs);
                }
                catch (Exception e) {
                    throw new RuntimeException(
                        "Exception thrown in onCreate() of "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
                try {
                     //  调用appclication的onCreate() (因为在创建appclication--makeApplication()的时候没有调用,所以这里会调用)
                    mInstrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!mInstrumentation.onException(app, e)) {
                        throw new RuntimeException(
                          "Unable to create application " + app.getClass().getName()
                          + ": " + e.toString(), e);
                    }
                }
            } finally {
                // If the app targets < O-MR1, or doesn't change the thread policy
                // during startup, clobber the policy to maintain behavior of b/36951662
                if (data.appInfo.targetSdkVersion <= Build.VERSION_CODES.O
                        || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
                    StrictMode.setThreadPolicy(savedPolicy);
                }
            }
    
            // Preload fonts resources
            FontsContract.setApplicationContextForResources(appContext);
            try {
                final ApplicationInfo info =
                        getPackageManager().getApplicationInfo(
                                data.appInfo.packageName,
                                PackageManager.GET_META_DATA /*flags*/,
                                UserHandle.myUserId());
                if (info.metaData != null) {
                    final int preloadedFontsResource = info.metaData.getInt(
                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                    if (preloadedFontsResource != 0) {
                        data.info.getResources().preloadFonts(preloadedFontsResource);
                    }
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    我们先来看一下getPackageInfoNoCheck->getPackageInfo

      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) {
                    // Caching not supported across users
                    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())) {
                    if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
                            : "Loading resource-only package ") + aInfo.packageName
                            + " (in " + (mBoundApplication != null
                                    ? mBoundApplication.processName : null)
                            + ")");
                    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) {
                        // Caching not supported across users
                    } else if (includeCode) {
                        mPackages.put(aInfo.packageName,
                                new WeakReference<LoadedApk>(packageInfo));
                    } else {
                        mResourcePackages.put(aInfo.packageName,
                                new WeakReference<LoadedApk>(packageInfo));
                    }
                }
                return packageInfo;
            }
        }
    

    我们再来看一下LoaderApk#makeApplication

        public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
             //  这里判断如果已经存在 则直接返回,在我们上个方法getPackageInfo中已经说过,首先会从缓存中获取
            //  如果有则直接返回 没有就创建,如果原先就有的话,那么mApplication   != null,当然这种情况是
            //  发生在应用内跳转的   如果是启动应用的话 mApplication   == null
            if (mApplication != null) {
                return mApplication;
            }
    
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
    
            Application app = null;
            //  先拿到Application类名
            String appClass = mApplicationInfo.className;
            if (forceDefaultAppClass || (appClass == null)) {
                appClass = "android.app.Application";
            }
    
            try {
                java.lang.ClassLoader cl = getClassLoader();
                if (!mPackageName.equals("android")) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "initializeJavaContextClassLoader");
                    initializeJavaContextClassLoader();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
               //  这里又创建了一个ContextImpl 
                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
               //  通过Instrumentation反射创建Application对象并调用其attach方法
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
               //  将appclication与contenxt进行关联(看来这里才是真正的context)
                appContext.setOuterContext(app);
            } catch (Exception e) {
                if (!mActivityThread.mInstrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to instantiate application " + appClass
                        + ": " + e.toString(), e);
                }
            }
            //  将appclication保存到activitythread中
            mActivityThread.mAllApplications.add(app);
            mApplication = app;
           // 我们前面传的是null  所以这里不会进入(创建activity的时候会再次调用这个方法,那个时候会进入这个判断)
            if (instrumentation != null) {
                try {
                    //  调用appclication的oncreate
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!instrumentation.onException(app, e)) {
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                            + ": " + e.toString(), e);
                    }
                }
            }
    
            // Rewrite the R 'constants' for all library apks.
            SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
            final int N = packageIdentifiers.size();
            for (int i = 0; i < N; i++) {
                final int id = packageIdentifiers.keyAt(i);
                if (id == 0x01 || id == 0x7f) {
                    continue;
                }
    
                rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
            }
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
          //  最后返回
            return app;
        }
    
    2)创建activity

    我们回到AMS的attachApplicationLocked,我们在创建完appclication之后,会通过ActivityStackSupervisor#创建activity

    
        boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
            final String processName = app.processName;
            boolean didSomething = false;
            //  获取到当前位于前台的ActivityStack,然后得到其栈顶运行的activity
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = stacks.get(stackNdx);
                    if (!isFocusedStack(stack)) {
                        continue;
                    }
                    stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
                    final ActivityRecord top = stack.topRunningActivityLocked();
                    final int size = mTmpActivityList.size();
                    for (int i = 0; i < size; i++) {
                        final ActivityRecord activity = mTmpActivityList.get(i);
                        if (activity.app == null && app.uid == activity.info.applicationInfo.uid
                                && processName.equals(activity.processName)) {
                            try {
                              //  最后调用这里
                                if (realStartActivityLocked(activity, app,
                                        top == activity /* andResume */, true /* checkConfig */)) {
                                    didSomething = true;
                                }
                            } catch (RemoteException e) {
                                Slog.w(TAG, "Exception in new application when starting activity "
                                        + top.intent.getComponent().flattenToShortString(), e);
                                throw e;
                            }
                        }
                    }
                }
            }
            if (!didSomething) {
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            }
            return didSomething;
        }
    

    我们来看下realStartActivityLocked

    
        final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                boolean andResume, boolean checkConfig) throws RemoteException {
    
            if (!allPausedActivitiesComplete()) {
                // While there are activities pausing we skipping starting any new activities until
                // pauses are complete. NOTE: that we also do this for activities that are starting in
                // the paused state because they will first be resumed then paused on the client side.
                if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                        "realStartActivityLocked: Skipping start of r=" + r
                        + " some activities pausing...");
                return false;
            }
            //  首先获取到TaskRecord和ActivityStack
            final TaskRecord task = r.getTask();
            final ActivityStack stack = task.getStack();
    
            beginDeferResume();
    
            try {
                r.startFreezingScreenLocked(app, 0);
    
                // schedule launch ticks to collect information about slow apps.
                r.startLaunchTickingLocked();
               // Activity与Application进行关联
                r.app = app;
    
                if (mKeyguardController.isKeyguardLocked()) {
                    r.notifyUnknownVisibilityLaunched();
                }
    
                // Have the window manager re-evaluate the orientation of the screen based on the new
                // activity order.  Note that as a result of this, it can call back into the activity
                // manager with a new orientation.  We don't care about that, because the activity is
                // not currently running so we are just restarting it anyway.
                if (checkConfig) {
                    final int displayId = r.getDisplayId();
                    final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                            getDisplayOverrideConfiguration(displayId),
                            r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
                    // Deferring resume here because we're going to launch new activity shortly.
                    // We don't want to perform a redundant launch of the same record while ensuring
                    // configurations and trying to resume top activity of focused stack.
                    mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
                            displayId);
                }
    
                if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
                        true /* isTop */)) {
                    // We only set the visibility to true if the activity is allowed to be visible
                    // based on
                    // keyguard state. This avoids setting this into motion in window manager that is
                    // later cancelled due to later calls to ensure visible activities that set
                    // visibility back to false.
                    r.setVisibility(true);
                }
    
                final int applicationInfoUid =
                        (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
                if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
                    Slog.wtf(TAG,
                            "User ID for activity changing for " + r
                                    + " appInfo.uid=" + r.appInfo.uid
                                    + " info.ai.uid=" + applicationInfoUid
                                    + " old=" + r.app + " new=" + app);
                }
    
                app.waitingToKill = null;
                r.launchCount++;
                r.lastLaunchTime = SystemClock.uptimeMillis();
    
                if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
    
                int idx = app.activities.indexOf(r);
                if (idx < 0) {
                    app.activities.add(r);
                }
                mService.updateLruProcessLocked(app, true, null);
                mService.updateOomAdjLocked();
    
                if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                        task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
                    setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE",
                            false);
                }
    
                try {
                    if (app.thread == null) {
                        throw new RemoteException();
                    }
                    List<ResultInfo> results = null;
                    List<ReferrerIntent> newIntents = null;
                    if (andResume) {
                        // We don't need to deliver new intents and/or set results if activity is going
                        // to pause immediately after launch.
                        results = r.results;
                        newIntents = r.newIntents;
                    }
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                            "Launching: " + r + " icicle=" + r.icicle + " with results=" + results
                                    + " newIntents=" + newIntents + " andResume=" + andResume);
                    EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
                            System.identityHashCode(r), task.taskId, r.shortComponentName);
                    if (r.isHomeActivity()) {
                        // Home process is the root process of the task.
                        mService.mHomeProcess = task.mActivities.get(0).app;
                    }
                    mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                            PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
                    r.sleeping = false;
                    r.forceNewConfig = false;
                    mService.showUnsupportedZoomDialogIfNeededLocked(r);
                    mService.showAskCompatModeDialogLocked(r);
                    r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
                    ProfilerInfo profilerInfo = null;
                    if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                        if (mService.mProfileProc == null || mService.mProfileProc == app) {
                            mService.mProfileProc = app;
                            ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
                            if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
                                if (profilerInfoSvc.profileFd != null) {
                                    try {
                                        profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
                                    } catch (IOException e) {
                                        profilerInfoSvc.closeFd();
                                    }
                                }
    
                                profilerInfo = new ProfilerInfo(profilerInfoSvc);
                            }
                        }
                    }
    
                    app.hasShownUi = true;
                    app.pendingUiClean = true;
                    app.forceProcessStateUpTo(mService.mTopProcessState);
                    // Because we could be starting an Activity in the system process this may not go
                    // across a Binder interface which would create a new Configuration. Consequently
                    // we have to always create a new Configuration here.
    
                    final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                            mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
                    r.setLastReportedConfiguration(mergedConfiguration);
    
                    logIfTransactionTooLarge(r.intent, r.icicle);
                    //  主要是这里 通过ActivityThread进行创建
                    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                            System.identityHashCode(r), r.info,
                            // TODO: Have this take the merged configuration instead of separate global
                            // and override configs.
                            mergedConfiguration.getGlobalConfiguration(),
                            mergedConfiguration.getOverrideConfiguration(), r.compat,
                            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                            r.persistentState, results, newIntents, !andResume,
                            mService.isNextTransitionForward(), profilerInfo);
    
                    if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                        // This may be a heavy-weight process!  Note that the package
                        // manager will ensure that only activity can run in the main
                        // process of the .apk, which is the only thing that will be
                        // considered heavy-weight.
                        if (app.processName.equals(app.info.packageName)) {
                            if (mService.mHeavyWeightProcess != null
                                    && mService.mHeavyWeightProcess != app) {
                                Slog.w(TAG, "Starting new heavy weight process " + app
                                        + " when already running "
                                        + mService.mHeavyWeightProcess);
                            }
                            mService.mHeavyWeightProcess = app;
                            Message msg = mService.mHandler.obtainMessage(
                                    ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                            msg.obj = r;
                            mService.mHandler.sendMessage(msg);
                        }
                    }
    
                } catch (RemoteException e) {
                    if (r.launchFailed) {
                        // This is the second time we failed -- finish activity
                        // and give up.
                        Slog.e(TAG, "Second failure launching "
                                + r.intent.getComponent().flattenToShortString()
                                + ", giving up", e);
                        mService.appDiedLocked(app);
                        stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                                "2nd-crash", false);
                        return false;
                    }
    
                    // This is the first time we failed -- restart process and
                    // retry.
                    r.launchFailed = true;
                    app.activities.remove(r);
                    throw e;
                }
            } finally {
                endDeferResume();
            }
    
            r.launchFailed = false;
            if (stack.updateLRUListLocked(r)) {
                Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
            }
    
            if (andResume && readyToResume()) {
                // As part of the process of launching, ActivityThread also performs
                // a resume.
                stack.minimalResumeActivityLocked(r);
            } else {
                // This activity is not starting in the resumed state... which should look like we asked
                // it to pause+stop (but remain visible), and it has done so and reported back the
                // current icicle and other state.
                if (DEBUG_STATES) Slog.v(TAG_STATES,
                        "Moving to PAUSED: " + r + " (starting in paused state)");
                r.state = PAUSED;
            }
    
            // Launch the new version setup screen if needed.  We do this -after-
            // launching the initial activity (that is, home), so that it can have
            // a chance to initialize itself while in the background, making the
            // switch back to it faster and look better.
            if (isFocusedStack(stack)) {
                mService.startSetupActivityLocked();
            }
    
            // Update any services we are bound to that might care about whether
            // their client may have activities.
            if (r.app != null) {
                mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
            }
    
            return true;
        }
    
    

    ActivityThread会通过scheduleLaunchActivity发送一条消息,最终调用到handleLaunchActivity

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
            mSomeActivitiesChanged = true;
    
            if (r.profilerInfo != null) {
                mProfiler.setProfiler(r.profilerInfo);
                mProfiler.startProfiling();
            }
    
            // Make sure we are running with the most recent config.
            handleConfigurationChanged(null, null);
    
            if (localLOGV) Slog.v(
                TAG, "Handling launch of " + r);
    
            // Initialize before creating the activity
            if (!ThreadedRenderer.sRendererDisabled) {
                GraphicsEnvironment.earlyInitEGL();
            }
            WindowManagerGlobal.initialize();
            //  获取到Activity对象 
            Activity a = performLaunchActivity(r, customIntent);
    
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
                reportSizeConfigurations(r);
                Bundle oldState = r.state;
                //  调用Activity的onResume方法,如果设置了pendingIntent,则会在调用onResume之前调用onNewIntent
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    
                if (!r.activity.mFinished && r.startsNotResumed) {
                    // The activity manager actually wants this one to start out paused, because it
                    // needs to be visible but isn't in the foreground. We accomplish this by going
                    // through the normal startup (because activities expect to go through onResume()
                    // the first time they run, before their window is displayed), and then pausing it.
                    // However, in this case we do -not- need to do the full pause cycle (of freezing
                    // and such) because the activity manager assumes it can just retain the current
                    // state it has.
                    performPauseActivityIfNeeded(r, reason);
    
                    // We need to keep around the original state, in case we need to be created again.
                    // But we only do this for pre-Honeycomb apps, which always save their state when
                    // pausing, so we can not have them save their state when restarting from a paused
                    // state. For HC and later, we want to (and can) let the state be saved as the
                    // normal part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                }
            } else {
                // If there was an error, for any reason, tell the activity manager to stop us.
                try {
                    ActivityManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
        }
    
    

    我们来看performLaunchActivity

    
        private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
    
            ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                        Context.CONTEXT_INCLUDE_CODE);
            }
    
            ComponentName component = r.intent.getComponent();
            if (component == null) {
                component = r.intent.resolveActivity(
                    mInitialApplication.getPackageManager());
                r.intent.setComponent(component);
            }
    
            if (r.activityInfo.targetActivity != null) {
                component = new ComponentName(r.activityInfo.packageName,
                        r.activityInfo.targetActivity);
            }
            //  为activity创建Context对象
            ContextImpl appContext = createBaseContextForActivity(r);
            Activity activity = null;
            try {
               //  通过反射创建activity
                java.lang.ClassLoader cl = appContext.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                r.intent.prepareToEnterProcess();
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(activity, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate activity " + component
                        + ": " + e.toString(), e);
                }
            }
    
            try {
                //  这里会直接返回,因为LoaderApk里面已经有Application了
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
                if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
                if (localLOGV) Slog.v(
                        TAG, r + ": app=" + app
                        + ", appName=" + app.getPackageName()
                        + ", pkg=" + r.packageInfo.getPackageName()
                        + ", comp=" + r.intent.getComponent().toShortString()
                        + ", dir=" + r.packageInfo.getAppDir());
    
                if (activity != null) {
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                    Configuration config = new Configuration(mCompatConfiguration);
                    if (r.overrideConfig != null) {
                        config.updateFrom(r.overrideConfig);
                    }
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                            + r.activityInfo.name + " with config " + config);
                    Window window = null;
                    if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                        window = r.mPendingRemoveWindow;
                        r.mPendingRemoveWindow = null;
                        r.mPendingRemoveWindowManager = null;
                    }
                    appContext.setOuterContext(activity);
                   //  调用activity的attach()
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.configCallback);
    
                    if (customIntent != null) {
                        activity.mIntent = customIntent;
                    }
                    r.lastNonConfigurationInstances = null;
                    checkAndBlockForNetworkAccess();
                    activity.mStartedActivity = false;
                    int theme = r.activityInfo.getThemeResource();
                    if (theme != 0) {
                        activity.setTheme(theme);
                    }
    
                    activity.mCalled = false;
                   //  下面两个判断都会调用activity的onCreate方法,不同的是如果activity异常销毁就会有状态值传回去,会进入if,
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onCreate()");
                    }
                    r.activity = activity;
                    r.stopped = true;
                    if (!r.activity.mFinished) {
                        activity.performStart();
                        r.stopped = false;
                    }
                    if (!r.activity.mFinished) {
                        if (r.isPersistable()) {
                            //  同上面说到的,如果activity异常退出,会回调onRestoreInstanceState()
                            if (r.state != null || r.persistentState != null) {
                                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                        r.persistentState);
                            }
                        } else if (r.state != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                        }
                    }
                    if (!r.activity.mFinished) {
                        activity.mCalled = false;
                        if (r.isPersistable()) {
                            mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                    r.persistentState);
                        } else {
                            mInstrumentation.callActivityOnPostCreate(activity, r.state);
                        }
                        if (!activity.mCalled) {
                            throw new SuperNotCalledException(
                                "Activity " + r.intent.getComponent().toShortString() +
                                " did not call through to super.onPostCreate()");
                        }
                    }
                }
                r.paused = true;
                //  将activity保存起来
                mActivities.put(r.token, r);
    
            } catch (SuperNotCalledException e) {
                throw e;
    
            } catch (Exception e) {
                if (!mInstrumentation.onException(activity, e)) {
                    throw new RuntimeException(
                        "Unable to start activity " + component
                        + ": " + e.toString(), e);
                }
            }
    
            return activity;
        }
    
    

    ok到这里,Activity算是完全启动起来了

    相关文章

      网友评论

          本文标题:Activity/应用(O/8.0)启动流程(四)创建appcl

          本文链接:https://www.haomeiwen.com/subject/ripjfqtx.html