Android进阶之App启动流程和源码详解

admin 2023年3月7日08:23:12评论22 views字数 28156阅读93分51秒阅读模式

前言

Android中有四大组件:Activity、Service、BroadcastReceiver、ContentProvider。我们最常接触也是用户直接感受到的就是Activity了,今天来就说说Android启动的执行过程和工作原理。

Activity是一种 展示型组件,用于展示给用户一个可以交互的页面。Activity是Android中最重要的组件,对用户来说,所有的Activity就是一个App的全部,而其他组件用户是不能直接感知的;

今天我们就来分析总结下app启动流程的场景和知识点

一、启动中设计到关键类详解      

1、启动流程设计到主要类  

  • ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期;

  • ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作;

  • ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯;

  • ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的;

  • Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作;

  • ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程;

  • ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像;

  • TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生;

  • 可以说,启动的流程就是通过这几个类之间不断通信的过程;

2、zygote

  • zygote意为“受精卵“。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外。

  • 在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。

  • 我们都知道,每一个App其实都是:一个单独的dalvik虚拟机

    一个单独的进程;

  • 所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。所以说,除了第一个zygote进程,其他应用所在的进程都是zygote的子进程;

3、SystemServer

SystemServer也是一个进程,而且是由zygote进程fork出来的

在zygote开启的时候,会调用ZygoteInit.main()进行初始化

public static void main(String argv[]) {     ...ignore some code...    //在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true     boolean startSystemServer = false;     for (int i = 1; i < argv.length; i++) {                if ("start-system-server".equals(argv[i])) {                    startSystemServer = true;                } else if (argv[i].startsWith(ABI_LIST_ARG)) {                    abiList = argv[i].substring(ABI_LIST_ARG.length());                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());                } else {                    throw new RuntimeException("Unknown command line argument: " + argv[i]);                }            }            ...ignore some code...         //开始fork我们的SystemServer进程     if (startSystemServer) {                startSystemServer(abiList, socketName);         }     ...ignore some code...}

startSystemServer()做了些什么

 /**留着这个注释,就是为了说明SystemServer确实是被fork出来的     * Prepare the arguments and fork for the system server process.     */    private static boolean startSystemServer(String abiList, String socketName)            throws MethodAndArgsCaller, RuntimeException {         ...ignore some code...        //留着这段注释,就是为了说明上面ZygoteInit.main(String argv[])里面的argv就是通过这种方式传递进来的        /* Hardcoded command line to start the system server */        String args[] = {            "--setuid=1000",            "--setgid=1000",            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",            "--capabilities=" + capabilities + "," + capabilities,            "--runtime-init",            "--nice-name=system_server",            "com.android.server.SystemServer",        };        int pid;        try {            parsedArgs = new ZygoteConnection.Arguments(args);            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);        //fork出来的 -_-|||            /* Request to fork the system server process */            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* For child process */        if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);            }            handleSystemServerProcess(parsedArgs);        }        return true;    }

4、ActivityManagerService

  • ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。

  • ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。

public final class SystemServer {    //zygote的主入口    public static void main(String[] args) {        new SystemServer().run();    }    public SystemServer() {        // Check for factory test mode.        mFactoryTestMode = FactoryTest.getMode();    }    private void run() {        ...ignore some code...        //加载本地系统服务库,并进行初始化         System.loadLibrary("android_servers");        nativeInit();        // 创建系统上下文        createSystemContext();        //初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class<T>),这个方法通过反射来启动对应的服务        mSystemServiceManager = new SystemServiceManager(mSystemContext);        //开启服务        try {            startBootstrapServices();            startCoreServices();            startOtherServices();        } catch (Throwable ex) {            Slog.e("System", "******************************************");            Slog.e("System", "************ Failure starting system services", ex);            throw ex;        }        ...ignore some code...    }

初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。

 private void createSystemContext() {        ActivityThread activityThread = ActivityThread.systemMain();        mSystemContext = activityThread.getSystemContext();        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);    }    //在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。    private void startBootstrapServices() {        ...ignore some code...        //初始化ActivityManagerService        mActivityManagerService = mSystemServiceManager.startService(                ActivityManagerService.Lifecycle.class).getService();        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);        //初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);        // 现在电源管理已经开启,ActivityManagerService负责电源管理功能        mActivityManagerService.initPowerManagement();        // 初始化DisplayManagerService        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);    //初始化PackageManagerService    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);    ...ignore some code...    }}

二、app启动流程图步骤介绍

Android进阶之App启动流程和源码详解

1、activity中的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity;

2、之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息,然后使用ActivityStackSupervisor.startSpecificActivityLocked,如果进程已经存在,则直接使用realStartActivityLocked,通过App的binder客户端的代理ApplicationThread调用回到bindApplication,走入Activity的启动流程;如果进程不存在则通过socket链接Zygote,请求fork新的进程;

3、App进程创建完成后,进程启动会调用ActivityThread.main方法,初始化主线程Handler,接着走入attach方法,然后通过AMS的代理调用AMS的attachApplication方法,并将App进程的通信代理ApplicationThread传入AMS;

4、AMS获取到ATMS调用ApplicationThread的bindApplication回到App进程的ActivityThread.ApplicationThread.bindApplication方法中,然后使用Handler切换到主线程执行handleBindApplication,这里初始化了App的进程名字、时间,用户的硬件配置,包括App的文件系统,创建了App的Context实例,Instrumentation实例,调用App的onCreate回调方法,同时告诉AMS APP初始化工作完毕;

5、AMS接着会调用ATMS的attachApplication,最后调用ClientLifecycleManager的scheduleTransaction方法,通过App的Binder代理ApplicationThread回到ActivityThread;

6、进入ActivityThread.ApplicationThread.scheduleTransaction方法之后就进入了Activity的onStart、onResume回调

创建进程之前的过程主要是AMS的内部信息收集的判断的过程,下面主要看一下App进程启动的源码流程;

三、启动源码流程解析

1、APP进程起点

一个App的程序入口到底是什么?是ActivityThread.main()

从应用进程被创建开始,ActivityThread.main被执行

public static void main(String[] args) {    ActivityThread thread = new ActivityThread();    thread.attach(false, startSeq);    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方法,然后将activity和AMS通信的Binder代理IApplicationThread实例传入AMS

@UnsupportedAppUsageprivate void attach(boolean system, long startSeq) {    sCurrentActivityThread = this;    mSystemThread = system;    if (!system) {        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",                                                UserHandle.myUserId());        RuntimeInit.setApplicationObject(mAppThread.asBinder());        final IActivityManager mgr = ActivityManager.getService();        try {            mgr.attachApplication(mAppThread, startSeq);        } 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 {                        ActivityTaskManager.getService().releaseSomeActivities(mAppThread);                    } catch (RemoteException e) {                        throw e.rethrowFromSystemServer();                    }                }            }        });    } }

2、AMS的attachApplication

接着进入AMS进程,ActivityManagerService.attachApplicationLocked 

 private final boolean attachApplicationLocked(IApplicationThread thread,            int pid, int callingUid, long startSeq) {            if (app.isolatedEntryPoint != null) {                // This is an isolated process which should just call an entry point instead of                // being bound to an application.                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);            } else if (instr2 != null) {                thread.bindApplication(processName, appInfo, providers,                        instr2.mClass,                        profilerInfo, instr2.mArguments,                        instr2.mWatcher,                        instr2.mUiAutomationConnection, testMode,                        mBinderTransactionTrackingEnabled, enableTrackAllocation,                        isRestrictedBackupMode || !normalMode, app.isPersistent(),                        new Configuration(app.getWindowProcessController().getConfiguration()),                        app.compat, getCommonServicesLocked(app.isolated),                        mCoreSettingsObserver.getCoreSettingsLocked(),                        buildSerial, autofillOptions, contentCaptureOptions);            } else {                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,                        null, null, null, testMode,                        mBinderTransactionTrackingEnabled, enableTrackAllocation,                        isRestrictedBackupMode || !normalMode, app.isPersistent(),                        new Configuration(app.getWindowProcessController().getConfiguration()),                        app.compat, getCommonServicesLocked(app.isolated),                        mCoreSettingsObserver.getCoreSettingsLocked(),                        buildSerial, autofillOptions, contentCaptureOptions);            }        } catch (Exception e) {        }        // See if the top visible activity is waiting to run in this process...        if (normalMode) {            try {                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());            } catch (Exception e) {                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);                badApp = true;            }        }        // Find any services that should be running in this process...        if (!badApp) {            try {                didSomething |= mServices.attachApplicationLocked(app, processName);                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");            } catch (Exception e) {                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);                badApp = true;            }        }        return true;    }
  • thread.bindApplication:该方法主要讲App进程的配置信息通过IApplicationThread Binder通信回传到ActivityThread中;

  • mAtmInternal.attachApplication:mAtmInternal实际就是ActivityTaskManager的实例,通过LocalServices加载;

    mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
  • 那么这里相当于走到了ActivityTaskManagerServer的attachApplication中;

3、APP的bindApplication

先看第一条:

注意:ActivityThread中存在于Binder通信的代理--》ApplicationThread extends IApplicationThread.Stub

ActivityThread--》ApplicationThread--》bindApplication

@Override        public final void bindApplication(String processName, ApplicationInfo appInfo,                ProviderInfoList providerList, 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, AutofillOptions autofillOptions,                ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {            setCoreSettings(coreSettings);            AppBindData data = new AppBindData();            data.processName = processName;            .....            sendMessage(H.BIND_APPLICATION, data);        }

这里的bindApplication主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication

handleBindApplication如下:

ActivityThread--》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;Application的onCreate方法private void handleBindApplication(AppBindData data) {          mBoundApplication = data;        mConfiguration = new Configuration(data.config);        mCompatConfiguration = new Configuration(data.config);         if (data.initProfilerInfo != null) {            mProfiler.profileFile = data.initProfilerInfo.profileFile;            mProfiler.profileFd = data.initProfilerInfo.profileFd;            mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;            mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;            mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;            if (data.initProfilerInfo.attachAgentDuringBind) {                agent = data.initProfilerInfo.agent;            }        }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();             mInstrumentation.callApplicationOnCreate(app);}

该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化

4、ATMS的attachApplication

接着看第二条:mAtmInternal.attachApplication

mAtmInternal.attachApplication最终会调用mRootActivityContainer.attachApplication(wpc)@HotPath(caller = HotPath.PROCESS_CHANGE)        @Override        public boolean attachApplication(WindowProcessController wpc) throws RemoteException {            synchronized (mGlobalLockWithoutBoost) {                return mRootActivityContainer.attachApplication(wpc);            }        }RootActivityContainer.attachApplicationboolean attachApplication(WindowProcessController app) throws RemoteException {    final String processName = app.mName;    boolean didSomething = false;    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {        final ActivityDisplay display = mActivityDisplays.get(displayNdx);        final ActivityStack stack = display.getFocusedStack();        if (stack != null) {            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);            //获取前台栈顶第一个非finishing的Activity            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.mUid == activity.info.applicationInfo.uid                        && processName.equals(activity.processName)) {                    try {                    //真正启动Activity                        if (mStackSupervisor.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) {        ensureActivitiesVisible(null, 0, false /* preserve_windows */);    }    return didSomething;}

接着调用ActivityStackSupervisor.realStartActivityLocked开始创建Activity

5、ASS的realStartActivityLocked

ActivityStackSupervisor.realStartActivityLockedfinal boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,            boolean andResume, boolean checkConfig) throws RemoteException {        try {            r.startFreezingScreenLocked(app, 0);            //启动tick,收集应用启动慢的信息            // schedule launch ticks to collect information about slow apps.            r.startLaunchTickingLocked();            r.setProcess(app);            try {                //创建Activity启动事务                // Create activity launch transaction.                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,                        r.appToken);                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),                        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, mService.isNextTransitionForward(),                        profilerInfo));                //设置目标事务的状态为onResume                // Set desired final state.                final ActivityLifecycleItem lifecycleItem;                if (andResume) {                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());                } else {                    lifecycleItem = PauseActivityItem.obtain();                }                clientTransaction.setLifecycleStateRequest(lifecycleItem);                //通过transaciton方式开始activity生命周期,onCreate,onStart,onResume                // Schedule transaction.                mService.getLifecycleManager().scheduleTransaction(clientTransaction);            } catch (RemoteException e) {            }        } finally {            endDeferResume();        }        return true;    }ClientLifecycleManager

创建ClientLifecycleManager和ClientTransactionHandler来辅助管理Activity的生命周期,注意

clientTransaction.addCallback是LaunchActivityItem

lifecycleItem是ResumeActivityItem

ClientLifecycleManager.scheduleTransaction最终会调用ClientTransaction的schedule方法

public void schedule() throws RemoteException {    mClient.scheduleTransaction(this);}

那么这个mClient是IApplicationThread的实例,那么此时也就回到了ActivityThread的ApplicationThread中

IApplicationThread getClient() {    return mClient;}

6、Activity的onCreate方法

APP的scheduleTransaction

ActivityThread的ApplicationThread中 @Override  public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {        ActivityThread.this.scheduleTransaction(transaction);  }

因为ActivityThread继承ClientTransactionHandler,所以到了ClientTransactionHandler中

 void scheduleTransaction(ClientTransaction transaction) {      transaction.preExecute(this);      sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); }

通过Handler发送消息EXECUTE_TRANSACTION到H中

 case EXECUTE_TRANSACTION:                    final ClientTransaction transaction = (ClientTransaction) msg.obj;                    mTransactionExecutor.execute(transaction);                    if (isSystem()) {                        // Client transactions inside system process are recycled on the client side                        // instead of ClientLifecycleManager to avoid being cleared before this                        // message is handled.                        transaction.recycle();                    }                    // TODO(lifecycler): Recycle locally scheduled transactions.                    break;

接着TransactionExecutor的execute方法

public void execute(ClientTransaction transaction) {        final IBinder token = transaction.getActivityToken();        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);        executeCallbacks(transaction);        executeLifecycleState(transaction);        mPendingActions.clear();        log("End resolving transaction");    }LaunchActivityItem.execute方法 @Override    public void execute(ClientTransactionHandler client, IBinder token,            PendingTransactionActions pendingActions) {        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,                mPendingResults, mPendingNewIntents, mIsForward,                mProfilerInfo, client);        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);    }client其实是在ActivityThread的实例,那么就回到了ActivityThread的handleLaunchActivity @Override    public Activity handleLaunchActivity(ActivityClientRecord r,            PendingTransactionActions pendingActions, Intent customIntent) {            final Activity a = performLaunchActivity(r, customIntent);            }

7、接着调用performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        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 {            java.lang.ClassLoader cl = appContext.getClassLoader();            //创建Activity的实例            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) {        }        try {            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) {               //获取Resources资源                appContext.getResources().addLoaders(                        app.getResources().getLoaders().toArray(new ResourcesLoader[0]));                appContext.setOuterContext(activity);                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,                        r.assistToken);                if (r.isPersistable()) {                //回调Activity的onCreat                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }            }        } catch (SuperNotCalledException e) {            throw e;        } catch (Exception e) {        }        return activity;    }

在performLaunchActivity中,主要是加载App的资源包,然后创建了Activity的context实例,并创建了Activity的实例,接着调用activity.attach方法,attach执行完之后调用了onCreate方法。

8、APP的activity.attach

activity.attachfinal void attach(Context context, ActivityThread aThread,            Instrumentation instr, IBinder token, int ident,            Application application, Intent intent, ActivityInfo info,            CharSequence title, Activity parent, String id,            NonConfigurationInstances lastNonConfigurationInstances,            Configuration config, String referrer, IVoiceInteractor voiceInteractor,            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {        attachBaseContext(context);        mFragments.attachHost(null /*parent*/);        //创建了PhoneWindow实例        mWindow = new PhoneWindow(this, window, activityConfigCallback);        //设置了WindowControllerCallback监听        mWindow.setWindowControllerCallback(this);        //设置了WindowCallback监听        mWindow.setCallback(this);        mWindow.setOnWindowDismissedCallback(this);        mWindow.getLayoutInflater().setPrivateFactory(this);        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {            mWindow.setSoftInputMode(info.softInputMode);        }        if (info.uiOptions != 0) {            mWindow.setUiOptions(info.uiOptions);        }        //线程对象赋值,即ActivityThread main方法所在的线程        mUiThread = Thread.currentThread();//初始化Activity的成员变量,包括windowmanager        mMainThread = aThread;        mInstrumentation = instr;        mToken = token;        mAssistToken = assistToken;        mIdent = ident;        mApplication = application;        mIntent = intent;        mReferrer = referrer;        mComponent = intent.getComponent();        mActivityInfo = info;        mTitle = title;        mParent = parent;        mEmbeddedID = id;        mLastNonConfigurationInstances = lastNonConfigurationInstances;        if (voiceInteractor != null) {            if (lastNonConfigurationInstances != null) {                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;            } else {                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,                        Looper.myLooper());            }        }        mWindow.setWindowManager(                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),                mToken, mComponent.flattenToString(),                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);        if (mParent != null) {            mWindow.setContainer(mParent.getWindow());        }        mWindowManager = mWindow.getWindowManager();        mCurrentConfig = config;        mWindow.setColorMode(info.colorMode);        setAutofillOptions(application.getAutofillOptions());        setContentCaptureOptions(application.getContentCaptureOptions());    }

activity.attach中主要

1.创建了PhoneWindow实例

2.设置了Window接口的监听

3.初始化了成员变量,包括线程和WindowManager

三、点击桌面图标启动

当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。但是,你有没有思考过Launcher到底是一个什么东西?

Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.javapublic final class Launcher extends Activity        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,                   View.OnTouchListener {                   }

auncher实现了点击、长按等回调接口,来接收用户的输入。既然是普通的App,那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启的应用呢?如果让你,你怎么做这个功能呢?捕捉图标点击事件,然后startActivity()发送对应的Intent请求呗!是的,Launcher也是这么做的,就是这么easy!

那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml

<FrameLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"    android:id="@+id/launcher">    <com.android.launcher2.DragLayer        android:id="@+id/drag_layer"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:fitsSystemWindows="true">        <!-- Keep these behind the workspace so that they are not visible when             we go into AllApps -->        <include            android:id="@+id/dock_divider"            layout="@layout/workspace_divider"            android:layout_marginBottom="@dimen/button_bar_height"            android:layout_gravity="bottom" />        <include            android:id="@+id/paged_view_indicator"            layout="@layout/scroll_indicator"            android:layout_gravity="bottom"            android:layout_marginBottom="@dimen/button_bar_height" />        <!-- The workspace contains 5 screens of cells -->        <com.android.launcher2.Workspace            android:id="@+id/workspace"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:paddingStart="@dimen/workspace_left_padding"            android:paddingEnd="@dimen/workspace_right_padding"            android:paddingTop="@dimen/workspace_top_padding"            android:paddingBottom="@dimen/workspace_bottom_padding"            launcher:defaultScreen="2"            launcher:cellCountX="@integer/cell_count_x"            launcher:cellCountY="@integer/cell_count_y"            launcher:pageSpacing="@dimen/workspace_page_spacing"            launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"            launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">            <include android:id="@+id/cell1" layout="@layout/workspace_screen" />            <include android:id="@+id/cell2" layout="@layout/workspace_screen" />            <include android:id="@+id/cell3" layout="@layout/workspace_screen" />            <include android:id="@+id/cell4" layout="@layout/workspace_screen" />            <include android:id="@+id/cell5" layout="@layout/workspace_screen" />        </com.android.launcher2.Workspace>    ...ignore some code...    </com.android.launcher2.DragLayer></FrameLayout>

程序列表界面,点击图标的时候会发生什么呢?实际上,程序列表界面使用的是AppsCustomizePagedView对象,所以我在这个类里面找到了onClick(View v)。

com.android.launcher2.AppsCustomizePagedView.java/** * The Apps/Customize page that displays all the applications, widgets, and shortcuts. */public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements        View.OnClickListener, View.OnKeyListener, DragSource,        PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,        LauncherTransitionable {     @Override    public void onClick(View v) {         ...ignore some code...        if (v instanceof PagedViewIcon) {            mLauncher.updateWallpaperVisibility(true);            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);        } else if (v instanceof PagedViewWidget) {                 ...ignore some code..         }     }         }

可以看到,调用的是

mLauncher.startActivitySafely(v, appInfo.intent, appInfo);

和上面一样!这叫什么?这叫殊途同归!

所以咱们现在又明白了一件事情:不管从哪里点击图标,调用的都是Launcher.startActivitySafely()。

下面我们就可以一步步的来看一下Launcher.startActivitySafely()到底做了什么事情。

 boolean startActivitySafely(View v, Intent intent, Object tag) {        boolean success = false;        try {            success = startActivity(v, intent, tag);        } catch (ActivityNotFoundException e) {            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);        }        return success;    }调用了startActivity(v, intent, tag) boolean startActivity(View v, Intent intent, Object tag) {        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        try {            boolean useLaunchAnimation = (v != null) &&                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);            if (useLaunchAnimation) {                if (user == null || user.equals(android.os.Process.myUserHandle())) {                    startActivity(intent, opts.toBundle());                } else {                    launcherApps.startMainActivity(intent.getComponent(), user,                            intent.getSourceBounds(),                            opts.toBundle());                }            } else {                if (user == null || user.equals(android.os.Process.myUserHandle())) {                    startActivity(intent);                } else {                    launcherApps.startMainActivity(intent.getComponent(), user,                            intent.getSourceBounds(), null);                }            }            return true;        } catch (SecurityException e) {        ...        }        return false;    }

这里会调用Activity.startActivity(intent, opts.toBundle()),这个方法熟悉吗?这就是我们经常用到的Activity.startActivity(Intent)的重载函数。而且由于设置了

 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

所以这个Activity会添加到一个新的Task栈中,而且,startActivity()调用的其实是startActivityForResult()这个方法。

@Override    public void startActivity(Intent intent, @Nullable Bundle options) {        if (options != null) {            startActivityForResult(intent, -1, options);        } else {            // Note we want to go through this call for compatibility with            // applications that may have overridden the method.            startActivityForResult(intent, -1);        }    }

所以我们现在明确了,Launcher中开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。

下次我们详细介绍下startActivity之后的流程

总结:

  • 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

  • system_server进程接收到请求后,向zygote进程发送创建进程的请求;

  • Zygote进程fork出新的子进程,即App进程;

  • App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

  • system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

  • App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

  • 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法


推荐阅读

Android Audio音频系统

深入详解Apk编译打包流程

Android Framework学习路线

Android Audio音频系统之深入浅出

Android Audio音频常见问题分析方法

Android10以上系统Audio音频遇到播放视频无声时的分析方法

干货|Android APP应用工程师转Framework工程师(仅此一篇够了)

Android中实现系统声音录制(内置声源的录制)-framework调用流程分析


Android进阶之App启动流程和源码详解

原文始发于微信公众号(哆啦安全):Android进阶之App启动流程和源码详解

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月7日08:23:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android进阶之App启动流程和源码详解https://cn-sec.com/archives/1590847.html

发表评论

匿名网友 填写信息