Android 桌面应用启动APP的流程

Posted 清浅岁月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 桌面应用启动APP的流程相关的知识,希望对你有一定的参考价值。

桌面应用启动APP的流程

一:概图

具体代码分析

zygote进程fork一个进程后调用ActivityThread的systemMain方法,也就是上图中的步骤3:

ActivityThread 相关代码,systemMain是app真正的入口方法:


    public static ActivityThread systemMain() 
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) 
            ThreadedRenderer.disable(true);
         else 
            ThreadedRenderer.enableForegroundTrimming();
        
        
        // 创建ActivityThread 对象
        ActivityThread thread = new ActivityThread();
        
        // attach
        thread.attach(true, 0);
        return thread;
    

调用ActivityThread的attach方法将,通过ams的代理获取到ApplicationThread,

后续AMS将通过ApplicationThread和该进程进行通信。

ApplicationThread 是ActivityThread的内部类

看一下ApplicationThread,通过IApplicationThread.Stub
经常搞AIDL的就很熟悉。


private class ApplicationThread extends IApplicationThread.Stub 

        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

        private int mLastProcessState = -1;

        private void updatePendingConfiguration(Configuration config) 
            synchronized (mResourcesManager) 
                if (mPendingConfiguration == null ||
                        mPendingConfiguration.isOtherSeqNewer(config)) 
                    mPendingConfiguration = config;
                
            
        
        
        
        ........
        
        
 


ApplicationThread与ActivityThread通过handler发送消息的。


private void attach(boolean system, long startSeq) 
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) 
            ViewRootImpl.addFirstDrawHandler(new Runnable() 
                @Override
                public void run() 
                    ensureJitEnabled();
                
            );
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            
            //  获取AMS的代理类 
           
            final IActivityManager mgr = ActivityManager.getService();
            try 
            
            //  将ApplicationThread回调给ActivtyManagferService
            // ApplicationThread 是activityThread与ActivityManagerService的通信桥梁 
            
                mgr.attachApplication(mAppThread, startSeq);
                
             catch (RemoteException ex) 
                throw ex.rethrowFromSystemServer();
            
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() 
                @Override public void run() 
                    if (!mSomeActivitiesChanged) 
                        return;
                    
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) 
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try 
                            mgr.releaseSomeActivities(mAppThread);
                         catch (RemoteException e) 
                            throw e.rethrowFromSystemServer();
                        
                    
                
            );
         else 
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try 
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                 //  创建application
                 
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                //  调用application的oncreate
                
                mInitialApplication.onCreate();
             catch (Exception e) 
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            
        

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> 
            synchronized (mResourcesManager) 
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) 
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) 
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    
                
            
        ;
        ViewRootImpl.addConfigCallback(configChangedCallback);
    

上面是一个app进程启动后的一些流程。下面进程启动后启动activity的流程。

activity的创建流程以及生命周期的回调都是从activi的创建开始的:

@Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) 
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) 
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled) 
            GraphicsEnvironment.earlyInitEGL();
        
        
        //  初始化WindowManagerGlobal
        WindowManagerGlobal.initialize();
		
			//  创建activity
			
        final Activity a = performLaunchActivity(r, customIntent);

        if (a != null) 
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            if (!r.activity.mFinished && pendingActions != null) 
                pendingActions.setOldState(r.state);
                pendingActions.setRestoreInstanceState(true);
                pendingActions.setCallOnPostCreate(true);
            
         else 
            // If there was an error, for any reason, tell the activity manager to stop us.
            try 
            
            // 如果创建失败,通知AMS
        
                ActivityManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                                
             catch (RemoteException ex) 
                throw ex.rethrowFromSystemServer();
            
        

        return a;
    

// 获取WindowManagerService



    public static void initialize() 
        getWindowManagerService();
    

    public static WindowManagerGlobal getInstance() 
        synchronized (WindowManagerGlobal.class) 
            if (sDefaultWindowManager == null) 
                sDefaultWindowManager = new WindowManagerGlobal();
            
            return sDefaultWindowManager;
        
    

    public static IWindowManager getWindowManagerService() 
        synchronized (WindowManagerGlobal.class) 
            if (sWindowManagerService == null) 
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try 
                    if (sWindowManagerService != null) 
                        ValueAnimator.setDurationScale(
                                sWindowManagerService.getCurrentAnimatorScale());
                    
                 catch (RemoteException e) 
                    throw e.rethrowFromSystemServer();
                
            
            return sWindowManagerService;
        
    

performLaunchActivity方法


private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) 
        
			.............
				
			//  创建content
			
        ContextImpl appContext = createBaseContextForActivity(r);
        
        // 反射创建activity
        
        Activity activity = null;
        try 
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) 
                r.state.setClassLoader(cl);
            
         catch (Exception e) 
            if (!mInstrumentation.onException(activity, e)) 
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            
        

        try 
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

           ..........
                appContext.setOuterContext(activity);
                
                // attach 方法
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

               .........

                activity.mCalled = false;
                
                // 回调oncreate方法
                if (r.isPersistable()) 
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                 else 
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                
                if (!activity.mCalled) 
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                
                r.activity = activity;
            
           ..........

        return activity;
    


allActivityOnCreate中的方法,调的是activity中的performCreate,


public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) 
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    

activity中performCreate中真正调用onCreate入参为Bundle

在activity的什么周期基本对应一个performXXX

activity的生命周期基本都由ActivityThread来管理的,来调的performXXX。


    final void performCreate(Bundle icicle) 
        performCreate(icicle, null);
    

    final void performCreate(Bundle icicle, PersistableBundle persistentState) 
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        if (persistentState != null) 
            onCreate(icicle, persistentState);
         else 
            onCreate(icicle);
        
        writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
        mActivityTransitionState.readState(icicle);

        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    

activity的attach方法


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,
            Window window, ActivityConfigCallback activityConfigCallback) 
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
			// 创建   PhoneWindow
			
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
  
        .........
        
		// 设置WindowManager
		
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) 
            mWindow.setContainer(mParent.getWindow());
        
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    

总结一下activity的创建过程:

1.先反射创建activty

2.再调activty的attach方法

3.回调oncreate

activty与window,以及view的绘制流程

activty与window以及windowManager以及view的相关准备工作主要是在attach方法中处理的。

一:activty的 attach方法:

1.创建PhoneWindow ,传递ActivityConfigCallback,应该是和activity回调数据的。
2.设置windowManager


 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,
            Window window, ActivityConfigCallback activityConfigCallback) 
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
        
        
        
		//	 创建 PhoneWindow
		
		
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        
     ..........
     
     
		// 设置setWindowManager


        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) 
            mWindow.setContainer(mParent.getWindow());
        
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    

二创建PhoneWindow的

PhoneWindow的构造方法:


    public PhoneWindow(Context context, Window preservedWindow,
            ActivityConfigCallback activityConfigCallback) 
        this(context);
        // Only main activity windows use decor context, all the other windows depend on whatever
        // context that was given to them.
        mUseDecorContext = true;
        if (preservedWindow != null) 
            mDecor = (DecorView) preservedWindow.getDecorView();
            mElevation = preservedWindow.getElevation();
            mLoadElevation = false;
            mForceDecorInstall = true;
            // If we're preserving window, carry over the app token from the preserved
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // the token will not be updated as for a new window.
            getAttributes().token = preservedWindow.getAttributes().token;
        
        // Even though the device doesn't support picture-in-picture mode,
        // an user can force using it through developer options.
        boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
                DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
        mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_PICTURE_IN_PICTURE);
        mActivityConfigCallback = activityConfigCallback;
    

关注点一:preservedWindow 入参的时候是null的,所以mDecor并未被赋值。我们看一下mDecor是什么时候被赋值的。


 private void installDecor() 
        mForceDecorInstall = false;
        if (mDecor == null) 
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) 
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            
         else 
            mDecor.setWindow(this);
        
        
.......



是在PhoneWindow的installDecor方法中赋值的,installDecor是被谁调用的呢?

是被setContentView调用的,setContentView熟悉不.

setContentView有几个重载的方法没有一一贴出来,但是都调用的installDecor


   @Override
    public void setContentView(int layoutResID) 
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) 
            installDecor();
         else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) 
            mContentParent.removeAllViews();
        

       ..........
    


看一眼installDecor具体做了什么。

    private void installDecor() 
        mForceDecorInstall = false;
        if (mDecor == null) 
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) 
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            
         else 
            mDecor.setWindow(this);
        
        if (mContentParent == null) 
        
        // 将我们通过acticity的setContentView的添加到mContentParent中
        
            mContentParent = generateLayout(mDecor);
      
      .................      
            
            



protected DecorView generateDecor(int featureId) 
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) 
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) 
                context = getContext();
             else 
                context = new DecorContext(applicationContext, getContext());
                if (mTheme != -1) 
                    context.setTheme(mTheme);
                
            
         else 
            context = getContext();
        
        
        
        // 这里
        
        return new DecorView(context, featureId, this, getAttributes());
    


DecorView最终是被new出来的,其实DecorView的父类是fragment。

activity的setContentView调用的phoneWindow的setContentView

 public void setContentView(@LayoutRes int layoutResID) 
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    


设置phoneWindow的manager

                
   public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) 
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) 
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    


使用的是WindowManagerImpl,是WindowManager的实现类,具体处理事务的是WindowManagerGlobal处理的

WindowManagerGlobal。

public final class WindowManagerImpl implements WindowManager 
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    private final Context mContext;
    private final Window mParentWindow;

    private IBinder mDefaultToken;

    public WindowManagerImpl(Context context) 
        this(context, null);
    

    private WindowManagerImpl(Context context, Window parentWindow) 
        mContext = context;
        mParentWindow = parentWindow;
    

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) 
        return new WindowManagerImpl(mContext, parentWindow);
    

    public WindowManagerImpl createPresentationWindowManager(Context displayContext) 
        return new WindowManagerImpl(displayContext, mParentWindow);
    

    /**
     * Sets the window token to assign when none is specified by the client or
     * available from the parent window.
     *
     * @param token The default token to assign.
     */
    public void setDefaultToken(IBinder token) 
        mDefaultToken = token;
    

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) 
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    

    @Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) 
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    

    private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) 
        // Only use the default token if we don't have a parent window.
        if (mDefaultToken != null && mParentWindow == null) 
            if (!(params instanceof WindowManager.LayoutParams)) 
                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
            

            // Only use the default token if we don't already have a token.
            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
            if (wparams.token == null) 
                wparams.token = mDefaultToken;
            
        
    

    @Override
    public void removeView(View view) 
        mGlobal.removeView(view, false);
    

    @Override
    public void removeViewImmediate(View view) 
        mGlobal.removeView(view, true);
    

    @Override
    public void requestAppKeyboardShortcuts(
            final KeyboardShortcutsReceiver receiver, int deviceId) 
        IResultReceiver resultReceiver = new IResultReceiver.Stub() 
            @Override
            public void send(int resultCode, Bundle resultData) throws RemoteException 
                List<KeyboardShortcutGroup> result =
                        resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY);
                receiver.onKeyboardShortcutsReceived(result);
            
        ;
        try 
            WindowManagerGlobal.getWindowManagerService()
                .requestAppKeyboardShortcuts(resultReceiver, deviceId);
         catch (RemoteException e) 
        
    

    @Override
    public Display getDefaultDisplay() 
        return mContext.getDisplay();
    

    @Override
    public Region getCurrentImeTouchRegion() 
        try 
            return WindowManagerGlobal.getWindowManagerService().getCurrentImeTouchRegion();
         catch (RemoteException e) 
        
        return null;
    



WindowManagerGlobal的部分代码,WindowManagerGlobal管理着整个当前这个应用的window,以及ViewRootImpl,WindowManager.LayoutParams。在handleLaunchActivity中已经调用WindowManagerGlobal.initialize获取到IWindowManager

就是通过他和windowManagerService进行通信的。

    private final ArrayList<View> mViews = new ArrayList<View>();
    private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
    private final ArrayList<WindowManager.LayoutParams> mParams =
            new ArrayList<WindowManager.LayoutParams>();
    private final ArraySet<View> mDyingViews = new ArraySet<View>();

    private Runnable mSystemPropertyUpdater;

    private WindowManagerGlobal() 
    

    public static void initialize() 
        getWindowManagerService();
    

    public static WindowManagerGlobal getInstance() 
        synchronized (WindowManagerGlobal.class) 
            if (sDefaultWindowManager == null) 
                sDefaultWindowManager = new WindowManagerGlobal();
            
            return sDefaultWindowManager;
        
    

    public static IWindowManager getWindowManagerService() 
        synchronized (WindowManagerGlobal.class) 
            if (sWindowManagerService == null) 
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try 
                    if (sWindowManagerService != null) 
                        ValueAnimator.setDurationScale(
                                sWindowManagerService.getCurrentAnimatorScale());
                    
                 catch (RemoteException e) 
                    throw e.rethrowFromSystemServer();
                
            
            return sWindowManagerService;
        
    

总结一下:

在activity创建后,调用activity的attach方法中创建phoneWindow,此时的mDecor是空的,之后调用oncreate方法,

在oncreate中调用setContentView后mDecor才被创建赋值,这也是为什么我们不setContentView屏幕就是黑的的原因。

这个时候phoneWindow和activt关联了。

view的绘制

在oncreate执行完后将执行onresume,那么view的绘制是什么时候开始的,从哪里开始的,谁管理view的绘制?带着这些问题我们找一下,

acticity的什么周期都是由ActivityThread管理的,从ActivityThread寻找;

handleResumeActivity调用performResumeActivity


    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) 
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        
        //调用performResumeActivity 调用acticity的onResume方法
        
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        
        
        
        if (r == null) 
            // We didn't actually resume the activity, so skipping any follow-up actions.
            return;
        

        final Activity a = r.activity;

        if (localLOGV) 
            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
        

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) 
            try 
            
            // 通知AMS,Activity将要显示
                willBeVisible = ActivityManager.getService().willActivityBeVisible(
                        a.getActivityToken());
             catch (RemoteException e) 
                throw e.rethrowFromSystemServer();
            
        
        if (r.window == null && !a.mFinished && willBeVisible) 
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) 
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) 
                    impl.notifyChildRebuilt();
                
            
            if (a.mVisibleFromClient) 
                if (!a.mWindowAdded) 
                    a.mWindowAdded = true;
                    
                    
                    
                    //调用wm 的addView添加到, wm是上文中的WindowManagerGlobal
                    wm.addView(decor, l);
                    
                    
                    
                 else 
                    // The activity will get a callback for this @link LayoutParams change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                
            
            
			........


    

performResumeActivity的相关代码:

 @VisibleForTesting
    public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
            String reason) 
        final ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) 
            Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
        
        if (r == null || r.activity.mFinished) 
            return null;
        
        if (r.getLifecycleState() == ON_RESUME) 
            if (!finalStateRequest) 
                final RuntimeException e = new IllegalStateException(
                        "Trying to resume activity which is already resumed");
                Slog.e(TAG, e.getMessage(), e);
                Slog.e(TAG, r.getStateString());
                // TODO(lifecycler): A double resume request is possible when an activity
                // receives two consequent transactions with relaunch requests and "resumed"
                // final state requests and the second relaunch is omitted. We still try to
                // handle two resume requests for the final state. For cases other than this
                // one, we don't expect it to happen.
            
            return null;
        
        if (finalStateRequest) 
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        
        try 
            r.activity.onStateNotSaved();
            r.activity.mFragments.noteStateNotSaved();
            checkAndBlockForNetworkAccess();
            if (r.pendingIntents != null) 
                deliverNewIntents(r, r.pendingIntents);
                r.pendingIntents = null;
            
            if (r.pendingResults != null) 
                deliverResults(r, r.pendingResults, reason);
                r.pendingResults = null;
            
            
            
            // 调用activity的performResume,performResume会调onResume的方法
            
            
            r.activity.performResume(r.startsNotResumed, reason);

            r.state = null;
            r.persistentState = null;
            r.setState(ON_RESUME);
         catch (Exception e) 
            if (!mInstrumentation.onException(r.activity, e)) 
                throw new RuntimeException("Unable to resume activity "
                        + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
            
        
        return r;
    

调用activity的performResume,performResume会调onResume的方法

梳理一下:
在handleResumeActivity处理那些事情:

  1. 调用performResumeActivity执行获取到ctivityClientRecord对象

  2. 通过ctivityClientRecord获取到activity,并调用onResume方法,注意此时view尚未绘制,尚未显示,也就是view的绘制从onresum执行,在view· 可见之间进行绘制的。

3.之后获取到windowManager,windownManager的实现类是WindowManagerImpl,内部使用的全局(应用级别)单例WindowManagerGlobal,
WindowManagerGlobal和WMS(windowManagerService)通信。

接下来看一下WindowManagerGlobal的addview之后如何处理view的绘制的。


  public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) 
        if (view == null) 
            throw new IllegalArgumentException("view must not be null");
        
        if (display == null) 
            throw new IllegalArgumentException("display must not be null");
        
        if (!(params instanceof WindowManager.LayoutParams)) 
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        if (parentWindow != null) 
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
         else 
            // If there's no parent, then hardware acceleration for this view is
            // set from the application's hardware acceleration setting.
            final Context context = view.getContext();
            if (context != null
                    && (context.getApplicationInfo().flags
                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) 
                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            
        

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) 
            // Start watching for system property changes.
            if (mSystemPropertyUpdater == null) 
                mSystemPropertyUpdater = new Runnable() 
                    @Override public void run() 
                        synchronized (mLock) 
                            for (int i = mRoots.size() - 1; i >= 0; --i) 
                                mRoots.get(i).loadSystemProperties();
                            
                        
                    
                ;
                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
            

            int index = findViewLocked(view, false);
            if (index >= 0) 
                if (mDyingViews.contains(view)) 
                    // Don't wait for MSG_DIE to make it's way through root's queue.
                    mRoots.get(index).doDie();
                 else 
                    throw new IllegalStateException("View " + view
                            + " has already been added to the window manager.");
                
                // The previous removeView() had not completed executing. Now it has.
            

            // If this is a panel window, then find the window it is being
            // attached to for future reference.
            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) 
                final int count = mViews.size();
                for (int i = 0; i < count; i++) 
                    if (mRoots.get(i).mWindow.asBinder() == wparams.token) 
                        panelParentView = mViews.get(i);
                    
                
            


				// 创建了一个ViewRootImpl
				
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

				将view,以及ViewRootImpl ,wparams 存储下
				
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);

            // do this last because it fires off messages to start doing things
            try 
            
            
            // 这里是关键调用ViewRootImpl的setview
            
                root.setView(view, wparams, panelParentView);
                
         
                
             catch (RuntimeException e) 
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) 
                    removeViewLocked(index, true);
                
                throw e;
            
        
    

ViewRootImpl 是view的最高等级,实现了view与windowManager的所需的而一些协议,实现了

View.AttachInfo.Callbacks和ThreadedRenderer.DrawCallbacks以及ViewParent的接口。

这是ViewRootImpl的注释:

/**
* The top of a view hierarchy, implementing the needed protocol between View
 * and the WindowManager.  This is for the most part an internal implementation
 * detail of @link WindowManagerGlobal.
 *
 * @hide
 */

public final class ViewRootImpl implements ViewParent,
    View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks

mWindowSession = WindowManagerGlobal.getWindowSession();

ViewRootImpl的构造方法会获取WindowManagerGlobal中wms的代理对象,在ViewRootImpl中处理wms相互处理。

还发现在ViewRootImpl中顶一个一个mSurface,直接new出来的。

// These can be accessed by any thread, must be protected with a lock.
// Surface can never be reassigned or cleared (use Surface.clear()).
public final Surface mSurface = new Surface();

 /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) 
        synchronized (this) 
            if (mView == null) 
                mView = view;
                
					...........
					
                mSoftInputMode = attrs.softInputMode;
                mWindowAttributesChanged = true;
                mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
                mAttachInfo.mRootView = view;
                mAttachInfo.mScalingRequired = mTranslator != null;
                mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                if (panelParentView != null) 
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                
                mAdded = true;
                int res; /* = WindowManagerImpl.ADD_OKAY; */

                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                
                // 调用了requestLayout
                
                requestLayout();
                
                
             ............

    


requestLayout这个方法时ViewParent的,他重写这个方法


 @Override
    public void requestLayout() 
        if (!mHandlingLayoutInLayoutRequest) 
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        
    


最终调用 performTraversals()方法,这个方法代码有点多就不贴了,

调用了
performMeasure
performLayout
performDraw

performMeasure 调用view的measure,view的measure调用onmeasure,就是我们自定义view需要实现的。


 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) 
        if (mView == null) 
            return;
        
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
        try 
            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
         finally 
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        
    

performLayout,也一样


    private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
            int desiredWindowHeight) 
        mLayoutRequested = false;
        mScrollMayChange = true;
        mInLayout = true;

        final View host = mView;
        if (host == null) 
            return;
        
        if (DEBUG_ORIENTATION || DEBUG_LAYOUT) 
            Log.v(mTag, "Laying out " + host + " to (" +
                    host.getMeasuredWidth() + ", " + host.getMeasuredHeight() + ")");
        

        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
        try 
            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

            mInLayout = false;
        
        
        .........
 
    

performDraw也是一样的,嗲用draw之后调用view
的draw,再调用onDraw。

就开始view的真正绘制了。

把绘制的流程总结一下:

1.在handleLaunchActivity >>>>>performLaunchActivity>>>>>>activty.attach>>>>>>

phoneWindon>>>decoview>>>oncreate>>>>handleResumeActivity>>>>>>>performeRsumeActivity>>>>

activity.onresunme>>>>>windowManage.addview>>>>>

windowManagerImpl>>>>>windowManagerGloable>>>>>> new ViewRootImpl>>>>>

ViewRootImpl.setView>>>>>>>requestLayout>>>>>>performMeasure,performLayout,performDraw>>>

view.measure,view.layout,view.draw>>>>>>view.onMeasure,view.onLayout,view.onDraw

ViewRootImpl

以上是关于Android 桌面应用启动APP的流程的主要内容,如果未能解决你的问题,请参考以下文章

Android系统启动流程分析

Android系统启动流程分析

Android系统启动流程分析

从launcher程序启动App流程分析

Android APP应用启动过程分析

Android APP应用启动过程分析