Android进阶 - 应用启动分析

Andorid系统启动后,就可以使用系统中的应用程序了,Android的应用程序的后缀是:apk,分为系统应用和用户应用,系统应用可在编译源码时,打包发行,用户应用则可以通过应用市场等来下载安装。Launcher本身也是一个系统应用,上一篇文章(Android入门-系统启动简介)提到,SystemServer是通过:ActivityStackSupervisor.startActivityLocked()来启动主屏幕应用的。其实,所有的Android应用都可以通过这种方法启动。
1、回顾Home启动

Android入门-系统启动简介已经分析了,Home的启动是通过ActivityManagerService.startHomeActivityLocked启动的:

  1. startHomeActivityLocked:
    frameworks/base/services/java/com/android/server/am/ActivityManagerService.java:

    //获取主屏幕Intent
    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }
    boolean startHomeActivityLocked(int userId) {
        ...
        // 获取主屏幕的Intent
        Intent intent = getHomeIntent();
        // 获取主屏幕的Activity信息(如:包名,Activity名,应用信息,进程名等)
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            // 设置主屏幕Intent的组件信息
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            // 获取主屏幕应用的进程信息
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
            	// 假如主屏幕应用进程未启动,则启动
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo);
            }
        }
    
        return true;
    }
  2. startActivityLocked:

    frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java:

    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
        moveHomeToTop();
        startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
                null, false, null);
    }

可以看出,SystemServer进程通过调用ActivityStackSupervisor.startActivityLocked()来启动主屏幕应用。

2、考查一个简单的应用启动例子

这里,我们创建一个HelloAndroid的应用,再创建一个TestCallApp的应用,尝试在TestCallApp里,启动HelloAndroid应用。

2.1、创建HelloAndroid应用

在Eclipse里,NewProject->AndroidApplicationProject,取名:HelloAndroid,package名为:com.helloandroid。按向导一直Next,最后点击finish。

打开AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.helloandroid" android:versioncode="1" android:versionname="1.0">

    <uses-sdk android:minsdkversion="19" android:targetsdkversion="19">

    <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.helloandroid.MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN">
                <action android:name="com.helloandroid.HELLO">
                <category android:name="android.intent.category.DEFAULT">
                <category android:name="android.intent.category.LAUNCHER">
            </category></category></action></action></intent-filter>
        </activity>
    </application>
</uses-sdk></manifest>

intent-filter下面已经有一个名为“android.intent.action.MAIN”的action和一个名为“android.intent.category.LAUNCHER”的category,这是用于在Launcher里点击用户图标来启动应用的。我们在intent-filter下新增一个名为“com.helloandroid.HELLO”的action和一个名为“android.intent.category.DEFAULT”的category,这样做是为了方便其他程序调用。本章暂不详细讨论Intent。

点击Run,安装并运行HelloAndroid应用。

2.2、创建TestCallApp应用

创建应用的方法同上,名称用:TestCallApp,包名为:com.testcallapp。打开fragment_main.xml,转至GraphicalLayout,拖一个Button放到界面上,ID为call_button。

转至MainActivity.java:

...
/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        // 加入下面代码
        Button b = (Button) rootView.findViewById(R.id.call_button);
        if (b != null)
            b.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setAction("com.helloandroid.HELLO");
                    startActivity(intent);
                }
            });
        return rootView;
    }
}
...
上面是在Activity里内嵌了一个Fragment碎片,如果没用Fragment,可以在Activity.OnCreate里写上面的代码。

点击Run,运行并安装此程序。点击”Call“按钮,即可启动HelloAndroid应用。

此案例说明了如何从一个应用里启动另一个应用,也是用Intent,通过Activity.startActivity()函数来调用。

2.3、启动过程分析

我们接着来分析此函数的原码:

  1. Activity.startActivity:

    frameworks/base/core/java/android/app/Activity.java:

    ...
    	public void startActivity(Intent intent) {
    	    startActivity(intent, null);
    	}
    	...
    	public void startActivity(Intent intent, 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);
            }
        }
    	...
    	public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                if (requestCode >= 0) {
                    // If this start is requesting a result, we can avoid making
                    // the activity visible until the result is received.  Setting
                    // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                    // activity hidden during this time, to avoid flickering.
                    // This can only be done when a result is requested because
                    // that guarantees we will get information back when the
                    // activity is finished, no matter what happens to it.
                    mStartedActivity = true;
                }
    
                final View decor = mWindow != null ? mWindow.peekDecorView() : null;
                if (decor != null) {
                    decor.cancelPendingInputEvents();
                }
                // TODO Consider clearing/flushing other event sources and events for child windows.
            } else {
            	// 从子Activity中启动,从下面的代码可以看出,事实上也是调用execStartActivity,与mParent==null的流程差不多。
                if (options != null) {
                    mParent.startActivityFromChild(this, intent, requestCode, options);
                } else {
                    // Note we want to go through this method for compatibility with
                    // existing applications that may have overridden it.
                    mParent.startActivityFromChild(this, intent, requestCode);
                }
            }
        }
        ...
        public void startActivityFromChild(Activity child, Intent intent, 
                int requestCode, Bundle options) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, child,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, child.mEmbeddedID, requestCode,
                    ar.getResultCode(), ar.getResultData());
            }
        }
    从上面的源代码可以看出调用过程:startActivity(intent)->startActivity(intent,options)->startActivityForResult(intent,-1,options);最终都走到了Instrumentation.execStartActivity()函数里。
  2. Instrumentation.execStartActivity:

    frameworks/base/core/java/android/app/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, null, options);
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
            }
            return null;
        }
        ...
    流程走到这里,突然看不到源码了,因为IActivityManager是一个接口,通过调用IActivityManager.startActivity函数,来启动Activity。那么,IActivityManager的实现类在哪?先来看看ActivityManagerNative.getDefault()干了什么:frameworks/base/core/java/android/app/ActivityManagerNative.java
  3. 获取ActivityManagerService服务调用代理:

    static public IActivityManager asInterface(IBinder obj) {
            if (obj == null) {
                return null;
            }
            IActivityManager in =
                (IActivityManager)obj.queryLocalInterface(descriptor);
            if (in != null) {
                return in;
            }
    
            return new ActivityManagerProxy(obj);
        }
    	...
        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;
            }
        };
    ActivityManagerNative.gDefault是一个私有的单例模式运行的成员变量,保存当前默认的IActivityManager,从create代码可以看出,gDefault是"activity"服务的一个通信代理,即:ActivityManagerProxy,通过IBinder与ActivityManagerService通信。这里不分析IBinder及Android进程间通信机制,这属于另一篇文章的范畴了。这里简单讲述如何流程如何到ActivityManagerService服务中的。
  4. ActivityManagerService服务调用:

    IBinder有一个非常关键的方法transact,对应的Binder就会有一个onTransact与之对应,即通过IBinder.transact发出指令后,会触发远程的onTransact函数运行。

    • 调用端:ActivityManagerProxy.startActivity

      frameworks/base/core/java/android/app/ActivityManagerNative.java

      class ActivityManagerProxy implements IActivityManager
      {
          ...
          public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                  String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                  int startFlags, String profileFile,
                  ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
              Parcel data = Parcel.obtain();
              Parcel reply = Parcel.obtain();
              data.writeInterfaceToken(IActivityManager.descriptor);
              data.writeStrongBinder(caller != null ? caller.asBinder() : null);
              data.writeString(callingPackage);
              intent.writeToParcel(data, 0);
              data.writeString(resolvedType);
              data.writeStrongBinder(resultTo);
              data.writeString(resultWho);
              data.writeInt(requestCode);
              data.writeInt(startFlags);
              data.writeString(profileFile);
              if (profileFd != null) {
                  data.writeInt(1);
                  profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
              } else {
                  data.writeInt(0);
              }
              if (options != null) {
                  data.writeInt(1);
                  options.writeToParcel(data, 0);
              } else {
                  data.writeInt(0);
              }
              // 通过IBinder.transact(),调用服务端
              mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
              reply.readException();
              int result = reply.readInt();
              reply.recycle();
              data.recycle();
              return result;
          }
          ...
      }
      通过调用IBinder.transact(START_ACTIVITY_TRANSACTION,...)来调用远端服务
    • 服务端:ActivityManagerService.onTransact,是由其父类ActivityManagerNative实现的:

      frameworks/base/core/java/android/app/ActivityManagerNative.java

      public abstract class ActivityManagerNative extends Binder implements IActivityManager{
      ...
          @Override
          public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                  throws RemoteException {
              switch (code) {
              case START_ACTIVITY_TRANSACTION:
              {
                  data.enforceInterface(IActivityManager.descriptor);
                  IBinder b = data.readStrongBinder();
                  IApplicationThread app = ApplicationThreadNative.asInterface(b);
                  String callingPackage = data.readString();
                  Intent intent = Intent.CREATOR.createFromParcel(data);
                  String resolvedType = data.readString();
                  IBinder resultTo = data.readStrongBinder();
                  String resultWho = data.readString();
                  int requestCode = data.readInt();
                  int startFlags = data.readInt();
                  String profileFile = data.readString();
                  ParcelFileDescriptor profileFd = data.readInt() != 0
                          ? data.readFileDescriptor() : null;
                  Bundle options = data.readInt() != 0
                          ? Bundle.CREATOR.createFromParcel(data) : null;
                  // 启动Activity
                  int result = startActivity(app, callingPackage, intent, resolvedType,
                          resultTo, resultWho, requestCode, startFlags,
                          profileFile, profileFd, options);
                  reply.writeNoException();
                  reply.writeInt(result);
                  return true;
              }
              ...
          }
          ...
      }
    现在我们知道了,流程最终是通过ActivityManagerService.startActivity来启动Activity的。
  5. ActivityManagerService.startActivity:

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

    ...
        @Override
        public final int startActivity(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo,
                String resultWho, int requestCode, int startFlags,
                String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                    resultWho, requestCode,
                    startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
        }
    
        @Override
        public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo,
                String resultWho, int requestCode, int startFlags,
                String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
            enforceNotIsolatedCaller("startActivity");
            userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                    false, true, "startActivity", null);
            // TODO: Switch to user app stacks here.
            return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                    null, null, options, userId);
        }
        ...
  6. ActivityStackSupervisor.startActivityMayWait:

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

    ...
        final int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
                String resultWho, int requestCode, int startFlags, String profileFile,
                ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
                Bundle options, int userId) {
            ...
            synchronized (mService) {
                ...
                int res = startActivityLocked(caller, intent, resolvedType,
                        aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                        callingPackage, startFlags, options, componentSpecified, null);
    
                ...
                if (outResult != null) {
                	// 回传结果
                    ...
                }
    
                return res;
            }
        }

又到了ActivityStackSupervisor.startActivityLocked函数了。

3. Launcher里启动应用

由于Launcher本身也是一个应用,所以,原理上来讲,Launcher里启动应用,应该和在其他应用里启动一个应用没有什么区别。我们来看看Launcher3的Launcher源代码:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

public class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                   View.OnTouchListener {
    ...
    public void onClick(View v) {
        ...
        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
        	//如果是快捷方式
            ...

            // Start activities
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
			// 启动Activity
            boolean success = startActivitySafely(v, intent, tag);

            mStats.recordLaunch(intent, shortcut);

            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } 
		...
    }
    ...
    
    boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
        	// 启动Activity
            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;
    }
    ...
}
Launcher判断点击一个快捷方式后,会调用startActivitySafely启动Activity,而startActivitySafely里,则是调用Activity.startActivity来启动,与我们之前的预测完全相同。

4. 应用进程启动

前面几节说了几种类型的应用启动方式,最终都是用ActivityStackSupervisor.startActivityLocked来启动一个应用。现在,我们沿着这个流程,继续往下分析,应用的进程是如何启动的。由于startActivityLocked函数的作用不仅仅是新启动一个应用,还可以启动程序内部的Activity,所以,函数写的较为复杂,逻辑较多,本文将略去与新应用启动无关的逻辑,简单分析新应用的启动流程。

4.1 startActivity

  1. ActivityStackSupervisor.startActivityLocked:

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

    final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity) {
        ...
        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
    
        if (allPausedActivitiesComplete()) {
            // If someone asked to have the keyguard dismissed on the next
            // activity start, but we are not actually doing an activity
            // switch...  just dismiss the keyguard now, because we
            // probably want to see whatever is behind it.
            dismissKeyguard();
        }
        return err;
    }
    final int startActivityUncheckedLocked(ActivityRecord r,
                ActivityRecord sourceRecord, int startFlags, boolean doResume,
                Bundle options) {
        ...
        boolean newTask = false;
        boolean keepCurTransition = false;
        ...
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
        }
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        mService.setFocusedActivityLocked(r);
        return ActivityManager.START_SUCCESS;
    }
    到了ActivityStack.startActivityLocked,函数名称相同,类不同。Android的代码写的真的不怎么样。
  2. ActivityStack.startActivityLocked:

    frameworks/base/services/java/com/android/server/am/ActivityStack.java

    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        if (taskForIdLocked(taskId) == null || newTask) {
        	// 如果是新任务,则将任务插入到任务列表顶端
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask);
            mWindowManager.moveTaskToTop(taskId);
        }
        TaskRecord task = null;
        if (!newTask) {
            ...
        }
        ...
    
        task = r.task;
    
        // Slot the activity into the history stack and proceed
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        // 将Activity插到任务的Activities顶端,一个任务可以有多个Activities
        task.addActivityToTop(r);
    	// 标记Activity已经在历史记录中
        r.putInHistory();
        r.frontOfTask = newTask;
        if (!isHomeStack() || numActivities() > 0) {
            // 非home下的窗口处理,略
            ...
        } else {
            // home下的窗口处理,涉及锁屏等,略
            ...
        }
        if (VALIDATE_TOKENS) {
            validateAppTokensLocked();
        }
    
        if (doResume) {
        	// 恢复或启动顶层的Activity,本函数之前已经将Activity置入顶层
            mStackSupervisor.resumeTopActivitiesLocked();
        }
    }
  3. ActivityStackSupervisor.resumeTopActivitiesLocked:

    这段代码在上一篇(Android入门 - 系统启动简介)的Launcher启动已经有描述,本文再次描述,因为后续流程不一样。
    frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

    boolean resumeTopActivitiesLocked() {
        return resumeTopActivitiesLocked(null, null, null);
    }
    
    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = getFocusedStack();
        }
        boolean result = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            if (isFrontStack(stack)) {
                if (stack == targetStack) {
                    result = stack.resumeTopActivityLocked(target, targetOptions);
                } else {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }
  4. ActivityStack.resumeTopActivityLocked:

    frameworks/base/services/java/com/android/server/am/ActivityStack.java

    final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }
    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
    	// 找到顶层的ActivityRecord
        // Find the first activity that is not finishing.
        ActivityRecord next = topRunningActivityLocked(null);
    
        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;
    
        if (next == null) {
        	// 此处启动Launcher,在上一篇文章有描述,不过,经过一翻流转,最终还是会回到本函数,但此时next不是null了。Android源码,哎。。。
            ...
        }
    	...
        if (next.app != null && next.app.thread != null) {
        	// 应用已经启动情况,有可能会重启动应用,此处不分析
            ...
    
        } else {
            ...
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
    上面的函数逻辑非常复杂,有许多的return语句,这些return之后,经过一翻流转有可能又进入此函数,进入另一个判断分支。本文不详细分析Activity的各种复杂管理,只讨论如何启动,所以,略去了这许多代码,我是服了Android的代码设计者,一些这么复杂的函数,怎么也应该分多个函数来实现。
  5. ActivityStackSupervisor.startSpecificActivityLocked:

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

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
    
        r.task.stack.setLaunchTime(r);
    
        if (app != null && app.thread != null) {
            // 如果进程已经运行。。。
            ...
        }
    
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    终于到了启动进程的一步了。

4.2 启动进程

  1. ActivityManagerService.startProcessLocked:

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

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        } else {
            // If this is an isolated process, it can't re-use an existing process.
            app = null;
        }
        ...
        if (app != null && app.pid > 0) {
            // 已经运行
            ...
        }
        ...
    
        if (app == null) {
        	// 创建进程信息
            app = newProcessRecordLocked(info, processName, isolated);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            mProcessNames.put(processName, app.uid, app);
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
        } else {
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, mProcessStats);
        }
    
        // If the system is not ready yet, then hold off on starting this
        // process until it is.
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            // 如果系统未准备好,则加入Hold队列...
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
            return app;
        }
    	// 启动进程,见下面的函数
        startProcessLocked(app, hostingType, hostingNameStr);
        return (app.pid != 0) ? app : null;
    }
    ...
    private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
        ...
        // 从Hold队列中移除
        mProcessesOnHold.remove(app);
    
        updateCpuStats();
    
        try {
            int uid = app.uid;
    
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            ...
            // 启动进程
            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, null);
    		...
    		// 设置app的pid
    		app.setPid(startResult.pid);
    		app.usingWrapper = startResult.usingWrapper;
            app.removed = false;
            synchronized (mPidsSelfLocked) {
            	// 非常关键,保存应用的信息,将来ActivityThread.attach启动Application时,要依据pid找到app的信息
                this.mPidsSelfLocked.put(startResult.pid, app);
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
            ...
        } catch (RuntimeException e) {
            // XXX do better error recovery.
            app.setPid(0);
            Slog.e(TAG, "Failure starting process " + app.processName, e);
        }
    }
    准备启动进程了。
  2. Process.start:

    frameworks/base/core/java/android/os/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[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }
    private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            // 组织一些进程启动参数,略去
    		...
            return zygoteSendArgsAndGetResult(argsForZygote);
        }
    }
    private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
            throws ZygoteStartFailedEx {
        // 连接Zygote服务器,在上一篇中,已经说明,Zygote启动后,会创建Socket服务器,等待客户端连接,处理Fork新进程
        openZygoteSocketIfNeeded();
    
        try {
        	// 向Zygote发送Fork进程的请求
            ...
            sZygoteWriter.write(Integer.toString(args.size()));
            sZygoteWriter.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");
                }
                sZygoteWriter.write(arg);
                sZygoteWriter.newLine();
            }
    
            sZygoteWriter.flush();
    	    // 接收来自Zygote的回复
            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            // Fork的进程ID,很重要
            result.pid = sZygoteInputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = sZygoteInputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            try {
                if (sZygoteSocket != null) {
                    sZygoteSocket.close();
                }
            } catch (IOException ex2) {
                // we're going to fail anyway
                Log.e(LOG_TAG,"I/O exception on routine close", ex2);
            }
    
            sZygoteSocket = null;
    
            throw new ZygoteStartFailedEx(ex);
        }
    }
    上面的过程就简单了,打开与Zygote服务器的套接字连接,并往套接字里发送请求,再接收回复,真正的进程创建过程在Zygote中。

4.3 在Zygote里启动进程

Zygote是所有Java的孵化器,Zygote启动时会自动启动SystemServer进程,并注册Socket服务器,监听客户端的请求,来Fork新的进程。

  1. Zygote启动,我们再来回顾一下ZygoteInit.main()函数:

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();
    		// 注册套接字服务器
            registerZygoteSocket();
            ...
    		// 启动SystemServer
            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
    
            Log.i(TAG, "Accepting command socket connections");
    		// 循环监听Socket请求
            runSelectLoop();
    
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }
  2. 监听请求:ZygoteInit.runSelectLoop()

    private static void runSelectLoop() throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        FileDescriptor[] fdArray = new FileDescriptor[4];
    	// server socket的index为0,由于不是client,所以,放peers里往一个null,保持index索引的同步。
    	// 其实,这个没有必要,后面的peers.get(index-1)就行。再次看不惯Android源代码。
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
    
        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;
    		...
            try {
                fdArray = fds.toArray(fdArray);
                index = selectReadable(fdArray); // 阻塞等待所有的套接字
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }
    
            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
            	// 如果索引为0,表示有新的client请求连接,创建一个新的ZygoteConnection,并加入peers和fds列表中
                ZygoteConnection newPeer = acceptCommandPeer();
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
            	// 如果是客户端Socket有数据,则执行一次操作
                boolean done;
                done = peers.get(index).runOnce();
    
                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }
    上面源码中的注释,已对说明了Zygote服务器的简单处理过程。每一个新的连接请求后,会执行runOnce,来处理请求。
  3. 处理请求:

    frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
    
        try {
        	// 读取参数列表
            args = readArgumentList();
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            Log.w(TAG, "IOException on command socket " + ex.getMessage());
            closeSocket();
            return true;
        }
    	...
        try {
            ...
            // fork进程
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName);
        } catch (IOException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } catch (ErrnoException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } catch (IllegalArgumentException ex) {
            logAndPrintError(newStderr, "Invalid zygote arguments", ex);
        } catch (ZygoteSecurityException ex) {
            logAndPrintError(newStderr,
                    "Zygote security policy prevents request: ", ex);
        }
        try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
    
                // should never get here, the child is expected to either
                // throw ZygoteInit.MethodAndArgsCaller or exec().
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }
    先readArgumentList()读取Socket中的数据参数,再通过Zygote.forkAndSpecialize创建一个新进程,最后是处理进程:handleChildProc。
  4. Fork进程:

    libcore/dalvik/src/main/java/dalvik/system/Zygote.java

    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName) {
        preFork();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName);
        postFork();
        return pid;
    }
    nativeForkAndSpecialize()是一个JNI调用,函数在art/runtime/native/dalvik_system_Zygote.cc中。

    static jint Zygote_nativeForkAndSpecialize(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
                                               jint debug_flags, jobjectArray rlimits, jint mount_external,
                                               jstring se_info, jstring se_name) {
        return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external, se_info, se_name, false);
    }
    和SystemServer进程启动一样,都到了ForkAndSpecializeCommon函数这里,本文不准备继续往下分析,有兴趣的朋友可以继续研究。这就完成了新进程的启动。
  5. 子进程处理(handleChildProc):

    frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

    private void handleChildProc(Arguments parsedArgs,
                FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
                throws ZygoteInit.MethodAndArgsCaller {
    	...
        if (parsedArgs.runtimeInit) {
            ...
        } else {
            String className;
            try {
            	// className类名,来自client的请求数据,即:android.app.ActivityThread,可看前面的代码分析
                className = parsedArgs.remainingArgs[0];
            } catch (ArrayIndexOutOfBoundsException ex) {
                logAndPrintError(newStderr,
                        "Missing required class name argument", null);
                return;
            }
    
            String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
            System.arraycopy(parsedArgs.remainingArgs, 1,
                    mainArgs, 0, mainArgs.length);
    
            if (parsedArgs.invokeWith != null) {
                WrapperInit.execStandalone(parsedArgs.invokeWith,
                        parsedArgs.classpath, className, mainArgs);
            } else {
            	// 装入class
                ClassLoader cloader;
                if (parsedArgs.classpath != null) {
                    cloader = new PathClassLoader(parsedArgs.classpath,
                            ClassLoader.getSystemClassLoader());
                } else {
                    cloader = ClassLoader.getSystemClassLoader();
                }
    
                try {
                	// 执行class的main函数
                    ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
                } catch (RuntimeException ex) {
                    logAndPrintError(newStderr, "Error starting.", ex);
                }
            }
        }
    }
    子进程装入android.app.ActivityThread类,并执行android.app.ActivityThread.main函数,应用启动完成。

到此为止,Android的应用进程启动完成,最终是Fork了一个新进程,并在新进程里载入了android.app.ActivityThread类,这样,我们也知道了,所有Android应用进程启动,都会用到android.app.ActivityThread类的。

5. 应用运行

应用进程启动后,就进入了消息循环,到进程退出。消息循环是在android.app.ActivityThread实现的。但到现在为止,还与我们的Activity没什么关系。接下来,我们看看,我们的Activity是怎么载入的。
前面已经分析了startProcessLocked()函数会请求Zygote服务器Fork一个进程,Zygote创建新进程后,会将进程id(pid)返回,startProcessLocked()会将pid保存ProcessRecord中,而ProcessRecord包含了我们要启动的应用的详细信息(如:Activity类名,包名等)。由于新进程与新ActivityThread之间,没有任何参数传递,唯一知道的是,ActivityThread在新进程里运行,能获取该进程的pid。所以,我们可以通过pid来得到ProcessRecord,进而得到要启动的应用的所有信息。

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

public static void main(String[] args) {
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

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

    AsyncTask.init();

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
	// 处理消息
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
上面这段代码很简单,没有什么地方用到了我们的Activity参数,Looper.loop()是循环处理消息的,此时,我们的Activity应该已经启动了,怎么启动的,我们还是不知道。看来,thread.attach(false),这句就非常关键了。我们来分析一下:

  1. ActivityThread.attach:

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

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            // 前面已经分析过: ActivityManagerNative.getDefault()。mrg实际上就是ActivityManagerProxy的实例,是一个ActivityManagerService的Binder通信代理
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
            	// 传入mAppThread,后面要用到
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } else {
            ...
        }
        ...
    }
    这里不再分析ActivityManagerProxy是如何到ActivityManagerService的了,请看前面的分析。mgr.attachApplication最终会进入ActivityManagerService.attachApplication函数。
  2. ActivityManagerService.attachApplication:

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

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
        	// call进程的pid
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            // 在线程中附上Application
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
    ...
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    	...
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
            	// 找到pid对应的app,保存的代码在startActivityLocked中。
            	// 疑问?由于startActivityLocked是在一个进程中调用,而attachApplicationLocked是经由Zygote创建的新进程中触发调用。怎么保证attachApplicationLocked调用之前,startActivityLocked代码已经执行至保存进程信息这一步呢?
                // synchronized代码似乎不能保证在get之前,一定会先put,只能保证mPidsSelfLocked不会被同时访问。万一套接字返回较慢,而ActivityThread的快速运行至本代码处,岂不是找不到app了?
                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) {
                Process.killProcessQuiet(pid);
            } else {
                try {
                    thread.scheduleExit();
                } catch (Exception e) {
                    // Ignore exceptions.
                }
            }
            return false;
        }
    	...
    	// 会设置app.thread=thread,后面会调用thread.scheduleLaunchActivity来启动Activity
        app.makeActive(thread, mProcessStats);
        ...
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                badApp = true;
            }
        }
        ...
        return true;
    }
  3. ActivityManagerService.attachApplication:

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

    boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
        boolean didSomething = false;
        final String processName = app.processName;
        // 找到app对应的ActivityRecord,并调用realStartActivityLocked启动Activity。
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            if (!isFrontStack(stack)) {
                continue;
            }
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (headless) {
                            Slog.e(TAG, "Starting activities not supported on headless device: "
                                    + hr);
                        } else if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (Exception e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                              + hr.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0);
        }
        return didSomething;
    }
    ...
    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
    	...
    
        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();
    	...
        final ActivityStack stack = r.task.stack;
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            ...
            // 启动Activity
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration), r.compat,
                    app.repProcState, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
    		...
    
        } catch (RemoteException e) {
            ...
            throw e;
        }
    	...
    
        return true;
    }
    app.thread是一个ApplicationThread实例,ApplicationThread是定义在ActivityThread里的一个私有类,继承自ApplicationThreadNative。而ApplicationThreadNative继承自Binder,并实现了IApplicationThread接口,可以作为Binder服务端。尽管是从Binder继承,但ApplicationThread.scheduleLaunchActivity并未走Binder通信通道,是直接的服务端函数调用。网上有资料说是走的ApplicationThreadProxy,再走IBinder.transact,最终才进入ApplicationThread.scheduleLaunchActivity,这种说法不正确,或者Android4.4有修改,因为Android4.4中ActivityThread.mAppThread并不是继承自ApplicationThreadProxy的类实例,而是继承自ApplicationThreadNative。
  4. ApplicationThread.scheduleLaunchActivity:

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

    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            int procState, Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    
        updateProcessState(procState, false);
    
        ActivityClientRecord r = new ActivityClientRecord();
    
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
    
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
    
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
    
        r.profileFile = profileName;
        r.profileFd = profileFd;
        r.autoStopProfiler = autoStopProfiler;
    
        updatePendingConfiguration(curConfig);
    
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    本函数流程比较简单,创建一个ActivityClientRecord,然后,发送LAUNCH_ACTIVITY消息,启动一个Activity。sendMessage是个啥玩意?在Win32程序里,这很常见,Java程序里,基本看不到。
  5. ActivityThread.sendMessage:

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

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }
    ...
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        // 一个成员变量,类为H,H类派生自Hander。
        mH.sendMessage(msg);
    }
  6. Handler.sendMessage:

    frameworks/base/core/java/android/os/Handler.java

    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
    ...
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    ...
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
    ...
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    	// 很重要,保存msg的target为this,即H类的实例
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
    上面的代码,其实是将msg放入到mQueue队列中。既然是消息队列机制,则是异步处理,流程走到这算是完成了。但我们还是不知道从什么地方启动Activity的,所以,我们必须找到读取消息队列并处理消息的代码。

6. Activity运行

上面我们已经知道,Activity的启动msg已经放到mQueue队列中,我们现在需要知道,什么时候从队列中取出消息,并加入处理,启动Activity。
先回顾一下ActivityThread.main()函数。

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

public static void main(String[] args) {
    ...
	// 初始化Lopper,Looper存有前面说的重要变量:mQueue消息队列。这是静态的,可供全局使用。
    Looper.prepareMainLooper();
    
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
	// 强制创建AsyncTask.sHandler实例
    AsyncTask.init();

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
	// 处理消息
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}
由上面可以看到Looper类至关重要,我们来看看prepareMainLooper()做了什么?

frameworks/base/core/java/android/os/Looper.java

public final class Looper {
	...
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
	...
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    ...
    public static Looper myLooper() {
        return sThreadLocal.get();
    }
}
先初始化sThreadLocal,并设置sThreadLocal为一个新创建的Looper。这样的话,sThreadLocal.get()就能得到这个Looper。Looper函数全局都用的是sThreadLocal.get()得到的Looper。

上节讲到,消息是通过Handler.sendMessage函数发送,其实就是放到Handler.mQueue成员保存的队列,Handler.mQueue来自哪里呢?

public final class ActivityThread {
	...
	final H mH = new H();
	...
	private class H extends Handler {
	...
	}
}

上面的H类无构造函数,new的时候执行的是Handler的默认构造函数。
frameworks/base/core/java/android/os/Handler.java

public class Handler {
...
	public Handler() {
	        this(null, false);
	}
	public Handler(Callback callback, boolean async) {
	    if (FIND_POTENTIAL_LEAKS) {
	        final Class<? extends Handler> klass = getClass();
	        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
	                (klass.getModifiers() & Modifier.STATIC) == 0) {
	            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
	                klass.getCanonicalName());
	        }
	    }
		// mLooper为Looper.myLooper(),此函数前面已经有分析
	    mLooper = Looper.myLooper();
	    if (mLooper == null) {
	        throw new RuntimeException(
	            "Can't create handler inside thread that has not called Looper.prepare()");
	    }
	    // 这里指定mQueue,来自mLooper.mQueue。
	    mQueue = mLooper.mQueue;
	    mCallback = callback;
	    mAsynchronous = async;
	}
...
}
经过上面的分析,我们知道,通过Handler.sendMessage发送的消息,其实是放在:Looper.myLooper().mQueue队列中,消息队列的变量来源已经确定。

下面来看,看到ActivityThread.main函数中,Looper.loop()是如何处理消息的。
frameworks/base/core/java/android/os/Looper.java

public final class Looper {
	...
    public static void loop() {
    	// 也是通过myLooper()获取Looper
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        // 获取消息队列,显然,与Handler.sendMessage用的是同一队列。
        final MessageQueue queue = me.mQueue;
		...
        for (;;) {
            Message msg = queue.next(); // might block
            
            ...
			// 消息调度
            msg.target.dispatchMessage(msg);
			
			...
        }
    }
    ...
}
msg.target是在发送消息时,由上节的代码ActivityThread.enqueueMessage中指定的,是ActivityThead的私有类H的实例。

frameworks/base/core/java/android/os/Handler.java

public class Handler{
	...
	public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
    ...
}
上面的msg.callback和mCallback都为null,所以,会进入handleMessage,即进入H.handleMessage中。

frameworks/base/core/java/android/os/Handler.java

public final class ActivityThread {...

final H mH = new H();

...

private class H extends Handler {

...

public void handleMessage(Message msg) {

if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

switch (msg.what) {

case LAUNCH_ACTIVITY: {

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");

ActivityClientRecord r = (ActivityClientRecord)msg.obj;

r.packageInfo = getPackageInfoNoCheck(

r.activityInfo.applicationInfo, r.compatInfo);

handleLaunchActivity(r, null);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

} break;

...

}

...

}

}

...

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Activity a = performLaunchActivity(r, customIntent);

if (a != null) {

r.createdConfig = new Configuration(mConfiguration);

Bundle oldState = r.state;

handleResumeActivity(r.token, false, r.isForward,

!r.activity.mFinished && !r.startsNotResumed);

...

} else {

// If there was an error, for any reason, tell the activity

// manager to stop us.

try {

ActivityManagerNative.getDefault()

.finishActivity(r.token, Activity.RESULT_CANCELED, null);

} catch (RemoteException ex) {

// Ignore

}

}

}

...

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 activity = null;

try {

java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

activity = mInstrumentation.newActivity(

cl, component.getClassName(), r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass());

r.intent.setExtrasClassLoader(cl);

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 {

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="

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值