Android应用程序启动详解(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lyz_zyx/article/details/82917033

Android系统的启动过程

我们应该都知道Android系统其实是基于Linux系统的。当我们长按下电源启动手机时,引导芯片开始从固化在ROM里的预设代码开始执行。加载引导程序Bootloader到RAM,然后执行。BootLoader是在Linux操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。在系统内核启动后,便会去设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。

init进程

在Linux中,第一个启动的进程就是init进程。然后后面所有的进程都是由init进程直接或者是间接创建出来的。init进程在启动后会初始化和启动属性服务,并且创建出一个名字很有意思的新的进程,它便是Zygote进程。

Zygote进程

Zygote进程也有人直接用中文叫“受精卵进程”。一个有意思的名字,使人很容易记住和想知道它是何方神圣。当然Android攻城狮命名不是随便定的,因为Zygote进程启动后,Android为了实现实现资源共用和更快的启动速度,通过Zygote进程直接去创建出子进程,也就是Android中所有app都是基于Zygote上的,当Zygote初始化完成之后,会创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动它第一个子进程SystemServer。

SystemServer进程

SystemServer进程作用是启动Binder线程池和SystemServiceManager,并且启动各种重要的系统服务,如:ActivityManagerService、PowerManagerService、PackageManagerService、WindowManagerService,等等80多个系统服务。

ActivityManagerService进程

ActivityManagerService进程启动后,会启动系统桌面Launcher。

Launcher

Launcher是一个特殊的app,它主要作用是用来显示widget和显示已装应用的快捷图标到界面上。当我们点击Launcher上的快捷图标后,就能启动app。

Android应用的启动过程

在android中的每一个app,都是独立运行在自己的进程中的。上面提到,当点击Launcher上的快捷图标后就会启动app。为什么点击快捷图标后就会启动app?因为Launcher源码告诉我们,它内部调用了startActivity:

       public void onClick(View v) {

        ……

        Object tag = v.getTag();

        if (tag instanceof ShortcutInfo) {

            // Open shortcut

            final Intent intent = ((ShortcutInfo) tag).intent;

            int[] pos = new int[2];

            v.getLocationOnScreen(pos);

            intent.setSourceBounds(new Rect(pos[0], pos[1],

                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));

                     //关键代码

            boolean success = startActivitySafely(v, intent, tag);

            if (success && v instanceof BubbleTextView) {

                mWaitingForResume = (BubbleTextView) v;

                mWaitingForResume.setStayPressed(true);

            }

        }

              ……

}
       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;

    }
       boolean startActivity(View v, Intent intent, Object tag) {

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {

            // Only launch using the new animation if the shortcut has not opted out (this is a

            // private contract between launcher and may be ignored in the future).

            boolean useLaunchAnimation = (v != null) &&

                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);

            if (useLaunchAnimation) {

                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,

                        v.getMeasuredWidth(), v.getMeasuredHeight());

                startActivity(intent, opts.toBundle());

            } else {

                startActivity(intent);

            }

            return true;

        } catch (SecurityException e) {

            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();

            Log.e(TAG, "Launcher does not have the permission to launch " + intent +

                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +

                    "or use the exported attribute for this activity. "

                    + "tag="+ tag + " intent=" + intent, e);

        }

        return false;

    }

因为Launcher类是继承于Activity的,所以上面调用的startActivity()就是Activity.java里的startActivity()方法。调了startActivity()方法后面会判断app的进程是否存在,若不存在,则会先建立app的进程。其步骤大概是这样:通过ActivityManagerService请求服务端Socket,服务端Socket再去请求Zygoto进程,然后Zygoto进程就会fork自身来创建app的进程。当app进程创建时,它的主线程也会被创建,此时app的第一个类ActivityThread的main()方法就会被调用,main()方法里头就会进行相关的初始化。这也是我们常说的Android中app第一个入口代码是ActivityThread.main()

从startActivity()到ActivityThread.main()流程源码分析

Activity.java

@Override

public void startActivity(Intent intent) {

    this.startActivity(intent, null);

}
@Override

public void startActivity(Intent intent, @Nullable Bundle options) {

    if (options != null) {

        startActivityForResult(intent, -1, options);

    } else {

        startActivityForResult(intent, -1);

    }

}
public void startActivityForResult(Intent intent, int requestCode) {

    startActivityForResult(intent, requestCode, null);

}
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {

    if (mParent == null) {
        // 关键代码1
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(

                this, mMainThread.getApplicationThread(), mToken, this,

                intent, requestCode, options);        
               ……
} else {
        // 关键代码2

        if (options != null) {

            mParent.startActivityFromChild(this, intent, requestCode, options);

        } else {

            mParent.startActivityFromChild(this, intent, requestCode);

        }

    }
……

}

可能看到,startActivity()方法最后是调用了startActivityForResult()方法,方法内做了一个mParent变量是否为空的判断,mParent其实也是一个Activity,关键代码2的中mParent.startActivityFromChild()方法里头也是调用了mInstrumentation.execStartActivity()方法,所以我们继续看关键代码1的execStartActivity()方法:

Instrumentation.java

public ActivityResult execStartActivity(

        Context who, IBinder contextThread, IBinder token, Activity target,

        Intent intent, int requestCode, Bundle options) {

    ……

    try {

        intent.migrateExtraStreamToClipData();

        intent.prepareToLeaveProcess();
            // 关键代码

        int result = ActivityManagerNative.getDefault()

            .startActivity(whoThread, who.getBasePackageName(), intent,

                    intent.resolveTypeIfNeeded(who.getContentResolver()),

                    token, target != null ? target.mEmbeddedID : null,

                    requestCode, 0, null, options);

        checkStartActivityResult(result, intent);

    } catch (RemoteException e) {

    }

    return null;

}

请看注释处关键代码 ActivityManagerNative.getDefault(),它返回一个IActivityManager对象,我们来看看getDefault()方法:

ActivityManagerNative.java

static public IActivityManager getDefault() {

    return gDefault.get();

}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {

    protected IActivityManager create() {

        IBinder b = ServiceManager.getService("activity");

        if (false) {

            Log.v("ActivityManager", "default service binder = " + b);

        }

        IActivityManager am = asInterface(b);

        if (false) {

            Log.v("ActivityManager", "default service = " + am);

        }

        return am;

    }

};

getDefault()方法中通过一个全局变量gDefault的get()方法返回对象出去,而gDefault变量中通过ServiceManager.getService(“activity”)初始化一个IBinder对象。它是通过Binder实现进程间通信的。很明显这里是用一个“activity”的key来获得对象,那么此key又在何处set,答案就在ActivityManagerService中,请看源码:

ActivityManagerService.java

public void setSystemProcess() {

    try {
        // 关键代码

        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

        ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);

        ServiceManager.addService("meminfo", new MemBinder(this));

        ServiceManager.addService("gfxinfo", new GraphicsBinder(this));

        ServiceManager.addService("dbinfo", new DbBinder(this));

        ……

    } catch (PackageManager.NameNotFoundException e) {

        throw new RuntimeException("Unable to find android system package", e);
    }
}

请看关键代码行,Context.ACTIVITY_SERVICE便是”activity”,而这里set进去的,便是ActivityManagerService自己。回到上面获得一个IActivityManager对象地方,此时我们便知它就是ActivityManagerService。所以startActivity 便是跨进程调用了ActivityManagerService里的startActivity()方法:

ActivityManagerService.java

@Override

public final int startActivity(IApplicationThread caller, String callingPackage,

        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

        int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,

        resultWho, requestCode, startFlags, profilerInfo, options,

        UserHandle.getCallingUserId());

}

@Override

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,

        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

        int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {

        ……
    // 关键代码
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,

            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,

            profilerInfo, null, null, options, userId, null, null);

}

ActivityStackSupervisor.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,

        String callingPackage, Intent intent, String resolvedType,

        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

        IBinder resultTo, String resultWho, int requestCode, int startFlags,

        ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,

        Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {

         ……
         // 关键代码

        int res = startActivityLocked(caller, intent, resolvedType, aInfo,

                voiceSession, voiceInteractor, resultTo, resultWho,

                requestCode, callingPid, callingUid, callingPackage,

                realCallingPid, realCallingUid, startFlags, options,

                componentSpecified, null, container, inTask);
        ……
        return res;
    }
}
final int startActivityLocked(IApplicationThread caller,

        Intent intent, String resolvedType, ActivityInfo aInfo,

        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

        IBinder resultTo, String resultWho, int requestCode,

        int callingPid, int callingUid, String callingPackage,

        int realCallingPid, int realCallingUid, int startFlags, Bundle options,

        boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,

        TaskRecord inTask) {
    ……
​​​​​​​    // 关键代码
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,

            startFlags, true, options, inTask);

    ……

    return err;

}
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,

        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,

        boolean doResume, Bundle options, TaskRecord inTask) {

     ……
if (r.resultTo == null && inTask == null && !addingToTask

            && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {

      ……

    } else if (sourceRecord != null) {

       ……

        if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {

            ……

        } else if (!addingToTask &&

                (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {

            final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);

            if (top != null) {

                final TaskRecord task = top.task;

                task.moveActivityToFrontLocked(top);

                ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);

                top.updateOptionsLocked(options);

                top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);

                targetStack.mLastPausedActivity = null;

                if (doResume) {
                    // 关键代码

                    targetStack.resumeTopActivityLocked(null);

                }

                return ActivityManager.START_DELIVERED_TO_TOP;

            }

        }       

    }

     return ActivityManager.START_SUCCESS;

}

startActivityUncheckedLocked()方法中,我们看到很多熟悉的FLAG,因为就是此方法处理Activity四种启动模式standard、singleTop、singleTask 和 singleInstance,由于代码较多,这里就省略不展开分析了。继续来看看resumeTopActivityLocked方法:

ActivityStack.java

final boolean resumeTopActivityLocked(ActivityRecord prev) {

    return resumeTopActivityLocked(prev, null);

}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {

    if (mStackSupervisor.inResumeTopActivity) {

        return false;

    }

    boolean result = false;

    try {

        ……
        // 关键代码

        result = resumeTopActivityInnerLocked(prev, options);

    } finally {

        mStackSupervisor.inResumeTopActivity = false;

    }

    return result;

}
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

    if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");

    ……

    // 找到一个栈顶的未finish的Activity的ActivityRecord.

    final ActivityRecord next = topRunningActivityLocked(null);

    ……

    if (next == null) {

        // 栈顶无Activity,直接启动Launcher

        ……

        return isOnHomeDisplay() &&

                mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");

    }

    ……
    // Activity所在的进程已经存在

    if (next.app != null && next.app.thread != null) {

        ……

        try {

            ……
            // 重新显示Activity

            if (next.newIntents != null) {

                next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);

            }

            ……
            // 执行Activity onResume()

            next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,

                    mService.isNextTransitionForward(), resumeAnimOptions);


            ……

        } catch (Exception e) {

            // 如果启动异常,就重启Activity

            ……

            mStackSupervisor.startSpecificActivityLocked(next, true, false);

            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();

            return true;

        }

        ……

    } else {

        // Activity所在的进程不存在,启动Activity

        if (!next.hasBeenLaunched) {

            ……

        } else {

            ……

        }
        // 关键代码
        mStackSupervisor.startSpecificActivityLocked(next, true, true);

    }

    ……

    return true;

}

方法里代码较多,直接对应看注释的说明,接着再来看看startSpecificActivityLocked方法:

ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r,

        boolean andResume, boolean checkConfig) {

    ProcessRecord app = mService.getProcessRecordLocked(r.processName,

            r.info.applicationInfo.uid, true);

    r.task.stack.setLaunchTime(r);


    // 再判断Activity所在进程判断,进程存在时,直接启动Activity

    if (app != null && app.thread != null) {

        try {

            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) {



                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats);

            }
            // 关键代码1
            realStartActivityLocked(r, app, andResume, checkConfig);

            return;

        } catch (RemoteException e) {

            Slog.w(TAG, "Exception when starting activity "

                    + r.intent.getComponent().flattenToShortString(), e);

        }

    }

    // 关键代码2
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);

}
在startSpecificActivityLocked()方法很重要,它对Activity的进程是否存在做了判断:

当Activity的进程存在时,直接调用关键代码的1的realStartActivityLocked()方法启动Activity;(请先记住:这是从应用中启动Activity所走的分支,后面我们再来分析)

当Activity的进程不存在时,就会调用关键代码2的ActivityManagerService的startProcessLocked()方法创建进程,我们本次是从Launcher启动的Activity的,进程当然是不存在,所以就会执行mService.startProcessLocked()来新建进程,我们来看看具体代码:

ActivityManagerService.java

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,

        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,

        boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,

        String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {

        ……

    if (app == null) {

        checkTime(startTime, "startProcess: creating new process record");

        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);

        if (app == null) {

            Slog.w(TAG, "Failed making new process record for "

                    + processName + "/" + info.uid + " isolated=" + isolated);

            return null;

        }

        app.crashHandler = crashHandler;

        mProcessNames.put(processName, app.uid, app);

        if (isolated) {

            mIsolatedProcesses.put(app.uid, app);

        }

        checkTime(startTime, "startProcess: done creating new process record");

    } else {

        // If this is a new package in the process, add the package to the list

        app.addPackage(info.packageName, info.versionCode, mProcessStats);

        checkTime(startTime, "startProcess: added package to existing proc");

    }

    ……
     // 关键代码

    startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);

    checkTime(startTime, "startProcess: done starting proc!");

    return (app.pid != 0) ? app : null;

}
private final void startProcessLocked(ProcessRecord app, String hostingType,

        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {

    ……

    try {

        ……
              // 关键代码

        if (entryPoint == null) entryPoint = "android.app.ActivityThread";

        Process.ProcessStartResult startResult = Process.start(entryPoint,

                app.processName, uid, uid, gids, debugFlags, mountExternal,

                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,

                app.info.dataDir, entryPointArgs);

        ……

    } catch (RuntimeException e) {

        ……

    }

}

可以看出,Process.start()方法传入的第一个参数是ActivityThread类名,我们知道ActivityThread类是app的入口类,再继续往下看:

Process.java

public static final ProcessStartResult start(final String processClass,

                              final String niceName,

                              int uid, int gid, int[] gids,

                              int debugFlags, int mountExternal,

                              int targetSdkVersion,

                              String seInfo,

                              String abi,

                              String instructionSet,

                              String appDataDir,

                              String[] zygoteArgs) {

    try {
            // 关键代码

        return startViaZygote(processClass, niceName, uid, gid, gids,

                debugFlags, mountExternal, targetSdkVersion, seInfo,

                abi, instructionSet, appDataDir, zygoteArgs);

    } catch (ZygoteStartFailedEx ex) {

        Log.e(LOG_TAG,

                "Starting VM process through Zygote failed");

        throw new RuntimeException(

                "Starting VM process through Zygote failed", ex);

    }

}

请看关键代码行,startViaZygote()方法名已经很明显了,就是开始通过Zygote启动进程,继续看:

private static ProcessStartResult startViaZygote(final String processClass,

                              final String niceName,

                              final int uid, final int gid,

                              final int[] gids,

                              int debugFlags, int mountExternal,

                              int targetSdkVersion,

                              String seInfo,

                              String abi,

                              String instructionSet,

                              String appDataDir,

                              String[] extraArgs)

                              throws ZygoteStartFailedEx {

    synchronized(Process.class) {

        ArrayList<String> argsForZygote = new ArrayList<String>();

        ……
        // 关键代码
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);

    }

}
private static ProcessStartResult zygoteSendArgsAndGetResult(

        ZygoteState zygoteState, ArrayList<String> args)

        throws ZygoteStartFailedEx {

    try {

        final BufferedWriter writer = zygoteState.writer;

        final DataInputStream inputStream = zygoteState.inputStream;

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

        writer.newLine();


        int sz = args.size();

        for (int i = 0; i < sz; i++) {

            String arg = args.get(i);

            if (arg.indexOf('\n') >= 0) {

                throw new ZygoteStartFailedEx("embedded newlines not allowed");

            }

            writer.write(arg);

            writer.newLine();

        }

        writer.flush();

        // Should there be a timeout on this?

        ProcessStartResult result = new ProcessStartResult();

        result.pid = inputStream.readInt();

        if (result.pid < 0) {

            throw new ZygoteStartFailedEx("fork() failed");

        }

        result.usingWrapper = inputStream.readBoolean();

        return result;

    } catch (IOException ex) {

        zygoteState.close();

        throw new ZygoteStartFailedEx(ex);

    }

}
到这里就会执行Zygote的一些原生方法,通过对Zygote的机制的了解,我们知道Zygote会fork自身进程来创建应用进程,进而执行ActivityThread的main方法。

总结

看源码难免会让人感到乏味和无趣,但主要记住关键点其实就足够了:

  1. Android系统启动后第一个进程是init进程,其实是Zygote进程
  2. Android里所有的app都是运行在自己单独的进程里,其进程是通过Zygote进程fork自身来创建出来的
  3. Android中所有app的入口都是ActivityThread.main()方法

 

猜你喜欢

转载自blog.csdn.net/lyz_zyx/article/details/82917033