AMS(ActivityManagerService)源码解析2,Android应用是如何被启动的

一个Android应用是如何被启动的

  • 前言
  • 总结
  • [1. 启动Application](#1. 启动Application)
    • [1.1 拉起一个新的进程](#1.1 拉起一个新的进程)
    • [1.2 启动Application](#1.2 启动Application)
    • [1.3 AMS阶段](#1.3 AMS阶段)
    • [1.4 创建Instrumentation和Application](#1.4 创建Instrumentation和Application)
  • [2. 启动Activity](#2. 启动Activity)
    • [2.1 回到AMS,启动第一个Activity](#2.1 回到AMS,启动第一个Activity)
  • 参考资料

前言

基于源码API 28,30以后的版本启动第一个Activity的逻辑不一样

我会只拿出我们需要关注的代码部分,因为源码太多全都看看不过来的。所以每次截代码都有省略

前言

源码只截取需要看的部分,其他部分会省略。

源码基于API 28也就是Android9.0,也就是源码还有ActivityStackSupervisor的这个版本

其他版本代码不太一样没有ActivityStackSupervisor,但是原理是相同的。

AOSP的源码在这个网站上看:http://aospxref.com/

总结

用流程总结app启动:

  1. 用户点击应用图标(或者其他方式打开app)
  2. 要打开app的进程(可能是桌面进程可能是别的Intent)通知zygote进程fork出一个新的进程用于承载app。
  3. ActivityThread通过main方法启动,通过跨进程通信,通知SystemServer进程
  4. SystemServer的AMS去找PMS拿对应的进程信息。
  5. AMS将进程信息PackageInfo返还给应用进程
  6. ActivityThread创建Instrumentation和通过反射的方式创建Application,
  7. Instrumentation调用application的生命周期。

用流程总结第一个Activity启动:

  1. AMS遍历mPackages里面的Activity标签之后,找到启动时所需要的那个Activity(根据Intent里面的那个启动标签)。
  2. 准备一个事务(clientTransaction),里面包括了Activity的启动(Callback)和拉到前台(lifecycleState)两件事。

后面的流程参考上一篇文章的第六节,我们只需要知道一旦往ActivityThread发了一个ClientTransaction之后,后面的流程就完全是固定的。

AMS(ActivityManagerService)源码解析,Activity是如何被打开的
https://blog.csdn.net/qq_41872247/article/details/125031721

1. 启动Application

1.1 拉起一个新的进程

首先我们需要明确一点的是,启动一个app,他的起点来自于桌面进程,桌面进程在用户点击app图标准备拉起app的时候,就会让Zygote进程去即使的fork一个新的app进程出来,然后寻找到这个新的app的ActivityThread类的Main方法进行执行。

这部分见https://blog.csdn.net/qq_41872247/article/details/125211491

1.2 启动Application

接下来我们就来到了ActivityThread的Main方法

java 复制代码
public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {

	private ApplicationThread mAppThread
        
    // 启动类
    public static void main(String[] args) {
		ActivityThread thread = new ActivityThread();
		thread.attach(false, startSeq);
	}

	private void attach(boolean system, long startSeq) {
		if(!system) {
			final IActivityManager mgr = ActivityManager.getService();
	        try {
	            mgr.attachApplication(mAppThread, startSeq);
	        } catch (RemoteException ex) {
	            throw ex.rethrowFromSystemServer();
	        }
        }
	}

	private class ApplicationThread extend IApplicationThread.Stub {}
}

到attach,我们就通过跨进程进行binder通信了,拿到了AMS对象。我们传的对象ApplicationThread就是ActivityThread的一个内部类,持有外部引用,这个类就是负责和AMS通信。

1.3 AMS阶段

java 复制代码
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    public final void attachApplication(IApplicationThread thread, long startSeq) {
    	synchronized (this) {
    		attachApplicationLocked(thread, callingPid, callingUid, startSeq);
    	}
    }

	private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
		
		ProcessRecord app;
		
		// 这段代码从PMS中请求App的数据
		if (app == null && startSeq > 0) {
            final ProcessRecord pending = mPendingStarts.get(startSeq);
            if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq
                    && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
                            startSeq, true)) {
                app = pending;
            }
        }
        
        if (app.isolatedEntryPoint != null) {
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (app.instr != null) {
            	// 走这里
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            }
    }
}

AMS这部分先去PMS里面拿到当前app的相关数据(之前写在AndroidManifest里面的解析后存在mPackages的内容),

然后再返回来给ApplicationThread(走到thread.bindApplication)。

1.4 创建Instrumentation和Application

java 复制代码
public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {
   
   private class ApplicationThread extend IApplicationThread.Stub {

		public final void bindApplication(很多入参) {
			AppBindData data = new AppBindData();
			// ....将App的数据都放进data里面
			sendMessage(H.BIND_APPLICATION, data);
		}
   }
}

这里第一次sendMsg了,就是handler的那套流程,最后走到的是外侧的一个bindApplication方法

java 复制代码
public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {
        
	private static class AndroidOs extends ForwardingOs {
	
		private void handleBindApplication(AppBindData data) {
			// 一般都是走上面
			if (ii != null) {
	            initInstrumentation(ii, data, appContext);
	        } else {
	            mInstrumentation = new Instrumentation();
	            mInstrumentation.basicInit(this);
	        }
			//.....省略无关代码
            Application app;
			try {
				// 创建appllication
				app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
				//......
				// Instrumentation自己的onCreate方法,等于自己的生命周期,忽视它
				mInstrumentation.onCreate(data.instrumentationArgs);
				//......
                mInstrumentation.callApplicationOnCreate(app);
            }
		}

		private void initInstrumentation(
            InstrumentationInfo ii, AppBindData data, ContextImpl appContext) {
            
            try {
	            final ClassLoader cl = instrContext.getClassLoader();
	            mInstrumentation = (Instrumentation)
	                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        	}
        	//init只是把一大堆东西给他赋值到成员变量里面
        	mInstrumentation.init(this, instrContext, appContext, component,
                data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
	        }
	}
}

他在这段代码中做了几件事:

  1. 创建Instrumentation对象
  2. 创建Application对象
  3. 调用Application的生命周期

Instrumentation的创建过程上面已经有了,接下来看makeApplicationInner是如何创建Application的:

java 复制代码
public final class LoadedApk {
	private Application makeApplicationInner(boolean forceDefaultAppClass,
            Instrumentation instrumentation, boolean allowDuplicateInstances) {
        Application app = null;
        app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        return app;
    }
}

public class Instrumentation {
	public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        // getFactory我们具体就不看了,最终就是返回一个AppComponentFactory的对象
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context); //这个attach,就是我们自己定义的Application类的生命周期的那个attach,由Instrumentation直接调用
        return app;
    }
}

public class AppComponentFactory {
	public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        // 走到最后还是反射创建的对象。
        return (Application) cl.loadClass(className).newInstance();
    }
}

虽然中间跨了很多个类,但是还是可以看得出来根本的那行代码还是反射创建Application对象。

最后看看Application的生命周期是如何被Instrumentation调用的

java 复制代码
public class Instrumentation {
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }
}

结果就是直接调用,没有任何转折。

2. 启动Activity

2.1 回到AMS,启动第一个Activity

  1. 代码回到AMS,刚刚AMS的代码还未执行完。
java 复制代码
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        //.. bind之后发生的事

		// See if the top visible activity is waiting to run in this process...
		// 查看在这个进程中顶部的Activity是否正在等待运行...   其实就是启动顶部Activity了
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
	}
}

public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
        RecentTasks.Callbacks {
	boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                if (!isFocusedStack(stack)) {
                    continue;
                }
                stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
                final ActivityRecord top = stack.topRunningActivityLocked();
                final int size = mTmpActivityList.size();
                for (int i = 0; i < size; i++) {
                    final ActivityRecord activity = mTmpActivityList.get(i);
                    if (activity.app == null && app.uid == activity.info.applicationInfo.uid
                            && processName.equals(activity.processName)) {
                        try {
                        	// 通过好几层的for循环遍历app里面所有的Activity,去寻找并启动app的启动页
                            if (realStartActivityLocked(activity, app,
                                    top == activity /* andResume */, true /* checkConfig */)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                           
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
        }
        return didSomething;
    }


	final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
        try {
			// 准备启动Activity的事务
            final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                    r.appToken);
            // 这里准备了一个LaunchActivityItem作为Callback,记住他,后面会用到
            clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                    profilerInfo));

            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
            	// 这里我们是启动Activity,所以走resume
                lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            // 这里准备了一个ResumeActivityItem作为LifecycleState,记住他,后面会用到
            clientTransaction.setLifecycleStateRequest(lifecycleItem);

			// 发送这个事务
			mService.getLifecycleManager().scheduleTransaction(clientTransaction);
            }
    }
}

AMS遍历了一下启动进程的所有Activity,找到启动时要用的那个,走到了realStartActivityLocked准备启动。

后面的流程参考这篇文章的第六节,是完全一样的

AMS(ActivityManagerService)源码解析,Activity是如何被打开的
https://blog.csdn.net/qq_41872247/article/details/125031721

参考资料

码牛学院VIP课程 VIP12-2021.12.03-這染机制-01 Activity. View. WMS的协调kerwin

AOSP的源码网站:http://aospxref.com/

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui