ActivityRecord、ActivityClientRecord、Activity的关系

  在阅读Activity启动流程的源码时遇到了ActivityRecord和ActivityClientRecord,那么它们两个和Activity有什么关系呢?

结论

  ActivityRecord、ActivityClientRecord、Activity,三者一一对应。

分析

  ActivityRecord是system_server进程中的对象,ActivityClientRecord和Activity都是App进程中的对象,那么三者之间是如何建立起一一对应的关系呢?下面我来分析下。

ActivityRecord

  在Activity启动流程中system_server进程会经历以下方法调用链:

ActivityManagerService.startActivity() 
ActvityiManagerService.startActivityAsUser() 
ActivityStackSupervisor.startActivityMayWait() 
ActivityStackSupervisor.startActivityLocked() 

  我们可以发现在ActivityStackSupervisor.startActivityLocked() 中创建了ActivityRecord。

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 ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        ActivityContainer container, TaskRecord inTask) {
   		 int err = ActivityManager.START_SUCCESS;

  		  ...
		
		ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, this, container, options);

		  ...

 	   err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);

        ...
        return err;
}
final class ActivityRecord {
	final IApplicationToken.Stub appToken; // window manager token

	ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
            int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
            ActivityInfo aInfo, Configuration _configuration,
            ActivityRecord _resultTo, String _resultWho, int _reqCode,
            boolean _componentSpecified, boolean _rootVoiceInteraction,
            ActivityStackSupervisor supervisor,
            ActivityContainer container, Bundle options) {
			……
			appToken = new Token(this, service);
			……
	}

	static class Token extends IApplicationToken.Stub {
		private final WeakReference<ActivityRecord> weakActivity;
        private final ActivityManagerService mService;

        Token(ActivityRecord activity, ActivityManagerService service) {
            weakActivity = new WeakReference<>(activity);
            mService = service;
        }
	}
}

  从上面代码中可以看出ActivityRecord有一个成员变量appToken,类型为Token,继承了IApplicationToken.Stub。很明显,appToken可以跨进程传输(因为IApplicationToken.Stub继承了Binder,appToken本身就是个Binder对象嘛)。而且Token中还持有ActivityRecord的弱引用,也就是说可以通过appToken找到ActivityRecord.
  讲到这里,是不是马上就有思路了。只要把appToken传到App进程中,并赋值给ActivityClientRecord和Activity,那么三者的一一对应关系不就建立来了吗。
  源码中也的确是这么做的。
  接下来,为了启动这个新的Activity,就会调用ActivityStackSupervisor.realStartActivityLocked()方法。

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
`		……
		app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
		……

}

  app.thread其实就是IApplicationThread对象,实际类型是ApplicationThreadProxy。这里又是Binder通信。

final class ProcessRecord {
	IApplicationThread thread; 
}

public interface IApplicationThread extends IInterface {
	……
	void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException;
     ……
}

public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread {
       ……
}

//system_server进程持有ApplicationThreadProxy
class ApplicationThreadProxy implements IApplicationThread {
		……
}

//App进程持有ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
	……
}

  调用scheduleLaunchActivity()方法将appToken传递给App进程。

ActivityClientRecord

  在system_server进程中的调用ActivityStackSupervisor.realStartActivityLocked()后,Android系统会在App进程中调用ApplicationThread.scheduleLaunchActivity()方法。

private class ApplicationThread extends ApplicationThreadNative {
	@Override
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
			……
			ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            ……
            //调用ActivityThread.sendMessage()
            sendMessage(H.LAUNCH_ACTIVITY, r);
	}

}

  可以看到ApplicationThread.scheduleLaunchActivity()方法中创建了ActivityClientRecord,并将token赋值给了该ActivityClientRecord。然后又将ActivityClientRecord发送给主线程ActivityThread处理。经历了以下方法调用链。

ActivityThread.sendMessage() 
ActivityThread.H.sendMessage() 
ActivityThread.H.handleMessage() 
ActivityThread.handleLauncherActivity() 
ActivityThread.performLauncherActivity()
public final class ActivityThread {
	……
	final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
	……
	private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
		……
		Activity activity = null;
    	try {
    		java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
	    	activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
         	……
    	 } catch (Exception e) {
          	 ……
    	 }

		try {
			……
			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);
			……
		}……
		……
		//以ActivityClientRecord.token为Key保存了ActivityClientRecord
		mActivities.put(r.token, r);
		……
	}	

}

  可以看到ActivityThread.performLauncherActivity()方法中创建了Activity,并调用了Activity.attach()。在Activity.attach()方法中传入了ActivityClientRecord.token。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {
	……
	private IBinder mToken;
	……
	final 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) {
		……
		mToken = token;
		……
	}
}

  然后在Activity.attach()中将ActivityClientRecord.token赋值给了Activity.mToken。至此,ActivityRecord、ActivityClientRecord、Activity三者的一一对应关系就建立完毕了。

Token的利用

  上文已经分析完ActivityRecord、ActivityClientRecord、Activity三者如何建立对应关系的了,那么Android系统又是如何利用这层对应关系的呢。熟悉Activity启动流程的同学都知道Activity的生命周期实际上是由AMS控制的,比如启动Activity时需要令上一个Activity执行onPause()方法。这时会经历以下方法调用链。

ActivityStack.startPausingLocked() 
IApplicationThread.schudulePauseActivity() 
ActivityThread.sendMessage() 
ActivityThread.H.sendMessage(); 
ActivityThread.H.handleMessage() 
ActivityThread.handlePauseActivity() 
ActivityThread.performPauseActivity() 
Activity.performPause() 
Activity.onPause() 
ActivityManagerNative.getDefault().activityPaused(token) 
ActivityManagerService.activityPaused() 
ActivityStack.activityPausedLocked() 
ActivityStack.completePauseLocked()
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
        boolean dontWait) {
    ...
    if (prev.app != null && prev.app.thread != null) {
        ……
        try {
            ……
            //prev就是当前获得焦点的ActivityRecord,现在的目的是令该ActivityRecord对应的Activity调用onPause()
            prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                    userLeaving, prev.configChangeFlags, dontWait);
        } catch (Exception e) {
            ……
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
    } else {
        mPausingActivity = null;
        mLastPausedActivity = null;
        mLastNoHistoryActivity = null;
    }
    ...
}

  上面代码注释处,将当前获得焦点的ActivityRecord的appToken发给App进程。接下来调用ActivityThread.performPauseActivity()

final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState) : null;
}

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
	……
	mInstrumentation.callActivityOnPause(r.activity);
	……
}

public class Instrumentation {
	public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
}

  之前启动Activity时会调用performLaunchActivity(ActivityClientRecord r, Intent customIntent),并在最后以token为Key,ActivityClientRecord为value保存ActivityClientRecord。然后到了performPauseActivity()中又会根据token取出对应ActivityClientRecord。再调用ActivityClientRecord中保存的activity的onPause()方法。

performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	……
	mActivities.put(r.token, r);
	……
}

  执行完performPauseActivity()方法后,还要告知AMS,onPause()方法调用完毕。将token传回AMS。

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
	……
	performPauseActivity(token, finished, r.isPreHoneycomb());
	……
	ActivityManagerNative.getDefault().activityPaused(token);
	……
}

  接着调用到ActivityStack.activityPausedLocked() 。

final class ActivityStack {
	final void activityPausedLocked(IBinder token, boolean timeout) {
       ……
        final ActivityRecord r = isInStackLocked(token);
        if (r != null) {
            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            if (mPausingActivity == r) {
                completePauseLocked(true);
            } else {
                ……
            }
        }
    }

	ActivityRecord isInStackLocked(IBinder token) {
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        return isInStackLocked(r);
    }
}

final class ActivityRecord {
	static ActivityRecord forTokenLocked(IBinder token) {
        try {
            return Token.tokenToActivityRecordLocked((Token)token);
        } catch (ClassCastException e) {
            Slog.w(TAG, "Bad activity token: " + token, e);
            return null;
        }
    }

	static class Token extends IApplicationToken.Stub {
	
		private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            if (r == null || r.task == null || r.task.stack == null) {
                return null;
            }
            return r;
        }
    }
}

  AMS收到token后,根据token中的弱引用找到了对应的ActivityRecord。最后判断找到的ActivityRecord是否与保存的mPausingActivity是同一个对象。若是,就执行completePauseLocked(true),说明AMS已经收到Activity已调用onPause()的消息。

最后

  ActivityRecord和ActivityClientRecord都是保存Activity信息的对象。只不过,ActivityRecord归system_server进程使用,ActivityClientRecord归App进程使用。

参考文章:

四大组件之ActivityRecord

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章