- ActiivtyManagerService的main(..)(该函数被调用的地方是是SystemServer.java的ServerThread的initAndLoop(),其所在线程是调用SystemServer.main(…)的线程):
- 先new一个AThread thr并启动, 然后一直无限循环thr.wait()直到thr.mService(ActivityManagerService mService) != null才会继续(即AMS所在的线程基本准备就绪).
- Athread的run()函数主要流程:
- Looper.prepare();使该线程可以以looper的方式进行工作(其实就是为该线程生成一个TLS的Looper对象), 接受post.
- 将该线程的优先级设置为THREAD_PRIORITY_**FOREGROUND, 优先级是前台级别的,基本不能被强制杀死**
- android.os.Process.setCanSelfBackground(false作用是如果后面再有将线程优先级设置为background-level的行为,则直接抛出异常);
- ActivityManagerService m = new ActivityManagerService(); 构造一个ActivityManagerService(), 可见其运行主体其实是在这个Athread线程上, 而不是调用main函数的线程.
- 以线程Athred对象为同步锁:
- mService = m(这样在main函数中等待的其他线程可以通过AThread对象得到AMS对象)
- mLooper = Looper.myLooper(); 将之前Looper.prepare()为此线程生成的TLS Looper对象也保存在Athread对象中. 以供其他模块使用(应该是为了能向AMS所在的线程投递任务)
- Watchdog.getInstance().addThread(new Handler(mLooper), getName());将AMS所在的线程加入到Watchdog的监视, 因为AMS所在线程是很关键的线程
- notifyAll();准备就绪, 唤醒在main函数等待的其他线程
- 以线程Athred对象为同步锁:
- 无限循环wait()指导该Athread的mReady = true. 从被等待变为等待角色.
- 在上面的等待结束以后(AMS真正配置就绪)调用Looper.loop()开始以Looper的形式工作
- 在上面的Athread终于就绪以后, 上面的无限循环wait()得以结束,继续进行下一步:
* 从thr的mService获取在AThread中被初始化的AMS.
- mSelf(其实是static变量) = m;
- ActivityThread at = ActivityThread.systemMain(); 得到一个为供System使用的ActivityThread对象(用户级别的App也有一个对应的ActivityThread). systemMain()函数的操作:
- HardwareRenderer.disable(true); System并不需要硬件加速功能.
- new一个ActivityThread -> thread.
- thread.attach(true, true代表这一个系统使用的ActivityThread);
- mSystemThread(也是static变量) = at;
- Context context = at.getSystemContext(),获得一个系统专用的Context;context.setTheme(android.R.style.Theme_Holo);其Theme使用Theme_Holo.
- m.mContext = context; 将这个context也赋予AMS.
- m.mFactoryTest = factoryTest;
- m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());
- m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper(AThread线程的Looper, 会进一步交给ActiivtyStack使用, 后者以此Looper对象构造一个ActivityStackHandler来处理投递过来Message, 在AThread线程上);
- m.mBatteryStatsService.publish(context); 下面三项是将context进一步挂到AMS内部的3个Service上.
- m.mUsageStatsService.publish(context);
- m.mAppOpsService.publish(context);
- 在上面的准备都完毕以后, 以thr为锁, 将thr.mReady设置为true,然后thr.notifyAll()将等待的Athread线程唤醒,继续进行其run()函数, 开始Loop().
- 调用m(AMS).startRunning(null(String pkg), null(String cls), null(String action), null(String data))(注意这个操作不是进行在AThread线程);
- mStartRunning = true.
- systemReady(null(Runnable goingCallback));
- AMS的构造函数:
- 构造两个BroadCastQueue(mFgBroadcastQueue/mBgBroadcastQueue), 分别代表foreground和background,并且这两个Queue分别被保存在mBroadcastQueues(数组)的第0和1个位置.
- mServices = new ActiveServices(this); mProviderMap = new ProviderMap(this); 这两个用来track Service和ContentProvider.
- 构建/data/system文件夹.
- 下面是构造一系列的Service(BatteryStatsService/ProcessStatsService/UsageStatsService/AppOpsService)
- 初始化Configuration:
- mConfiguration.setToDefaults();
- mConfiguration.setLocale(Locale.getDefault());
- mConfigurationSeq = mConfiguration.seq = 1; sequenece初始化起始值为1
- 构建一个CompatModePackages用于兼容case.
- 将自己加入到WatchDog的Monitors.
- new 一个Thread(mProcessCpuThread)并start.
- 该Thread的任务是定时的调用updateCpuStatsNow()来更新当前的CPU信息
- 接着SystemServer的ServerThread的initAndLoop()在調用了AMS的main(…)以后, 会调用AMS的setSystemProcess():
- 该函数是一个static函数,因此需要通过mSelf(之前构造的AMS对象保存在这个static变量中)获取要操作的AMS对象.
- 调用ServiceManager.addService(…)加入一系列的Service:
- ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true); 将AMS作为ACTIVITY_SERVICE加入到系统Service中, 这样其他进程才能够通过ServiceManager来获取AMS的BpBinder进而进行通信
- ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats);
- ServiceManager.addService(“meminfo”, new MemBinder(m));
- ServiceManager.addService(“gfxinfo”, new GraphicsBinder(m));
- ServiceManager.addService(“dbinfo”, new DbBinder(m));
- ServiceManager.addService(“cpuinfo”, new CpuBinder(m));
- ServiceManager.addService(“permission”, new PermissionController(m));
- 上面几项也都是加入特定的系统服务, 可以看到AMS是身兼数职的
- 获取该进程的ActivityThread(mSystemThread)要装载的Application的ApplicationInfo:
- mSelf.mContext.getPackageManager().getApplicationInfo(“android”, STOCK_PM_FLAGS); 可以看到, 这个要加载的Application的PackageName是”android”
- 进一步进到getApplicationInfo(…)中,可以发现,对于PackageName为”android”/system”的请求,会返回mAndroidApplication, 而mAndroidApplication则是在PackageManagerService的scanPackageLI(…)中在扫描到PackageName为”android”的Package时所赋予的. 表明这个Package就是系统Package
- 得到了代表系统APK的AppliationInfo后, 调用ActivityThrea的installSystemApplicationInfo(info):
- 主要操作是对getSystemContext()得到的ContextImpl调用init(new LoadedApk(this, “android”, context, info, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this), 初始化该ActivityThread的SystemContext.
- 基于上面得到的info构造一个ProcessRecord(代表一个进程, 这个对象可以看作是在Android层面对于一个进程的认知和记录) app: mSelf.newProcessRecordLocked(info, info.processName, false)
- app.persistent = true; 该进程的persistent为true代表其会一直存在,即使被杀或者某些原因结束,也会自动重启
- app.pid = MY_PID; 进程号pid自然就是当前进程的pid
- app.maxAdj = ProcessList.SYSTEM_ADJ; 进程的maxAdj设置为SYSTEM_ADJ代表这是一个系统级的进程
- app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats); 将该ProcessRecord的thread变量(IApplicationThread)设置为AMS的SystemThread(ActivityThread)的getApplicationThread(), 使得通过ProcessRecord的thread就可以和AMS的SystemThread进行通信
- mSelf.mPidsSelfLocked.put(app.pid, app); AMS自己也保存了一份ProcessRecord对像和PID的Map
- mSelf.updateLruProcessLocked(app, true, false);
- mSelf.mContext.getPackageManager().getApplicationInfo(“android”, STOCK_PM_FLAGS); 可以看到, 这个要加载的Application的PackageName是”android”
- ContextImpl的init(new LoadedApk(this, “android”, context, info(ApplicationInfo), CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this(ActivityThread)) 主要跟踪的是Resources对象的获取:
- 转发到init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread, Resources container(null), String basePackageName(null), UserHandle user(Process.myUserHandle()))
- mPackageInfo = packageInfo;
- mResources = mPackageInfo(LoadedApk).getResources(mainThread);对接mResources到Package的资源
- LoadedApk的getResources(ActivityThread mainThread):
- 如果LoadedApk的mResources之前没有生成, 那么mResources = mainThread.getTopLevelResources(mResDir, Display.DEFAULT_DISPLAY, null, this);
- ActivityThread的getTopLevelResources(…) -> mResourcesManager.getTopLevelResources()
- 而ActivityThread的mResourcesManager在ActivityThread的构造函数中赋予, 是ResourcesManager的单例
- ResourcesManager的getTopLevelResources(String resDir, ….):
- 会以输入的resDir, displayId等参数生成ResourcesKey, 从mActiveResources中查找是否有缓存的Resources
- 如果没有, 那么new一个AssetManager, 并将resDir加入到其中: assets.addAssetPath(resDir)
- 根据displayId获得对应的DispalyMetric(dm): getDisplayMetricsLocked(displayId)
- 根据displayId以及hasOverrideConfig得到一个合适的Configuration对象.
- 然后以生成的AssetManager,DispalyMetrci和Configuration以及compatInfo/token(IBinder)为参数构造一个Resources对象.
- 将生成的Resoureces对象和对应的ResourcesKey都放入到mActiveResources中(对Resources的引用是若引用), 并返回此Resources对象.
- 可见,决定Resources对象资源地址的一个最主要的因素是ResDir, 而这里的ResDir是ApplicationInfo指定的LoadedApk的mResdir:
- 而LoadedApk的mResDir则是在LoadedApk的构造函数中被赋值的:
- mResDir = aInfo(ApplicationInfo).uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;:
- 如果AppliationInfo的uid就是进程的Id(myUid = Process.myUid()), 那么mResDir就是ApplicatiionInfo的sourceDir
- 否则则是ApplicatiionInfo的publicSourceDir
- 从这里可以看出对ResDir的权限控制, 对于uid一致的情况, 就认为是主人,可以获取完全的控制(sourceDir), 否则就只能访问开放出的公开资源(publicSourceDir)
- ApplicationInfo的sourceDir和publicSourceDir:
- sourceDir: Full path to the location of this package., 即对应Package的存放路径
- **publicSourceDir: Full path to the location of the publicly available parts of this
package (i.e. the primary resource package and manifest). For non-forward-locked apps this will be the same as sourceDir.** 可见还需要进一步去探索ApplicationInfo的生成和设置过程.
- mResourcesManager = ResourcesManager.getInstance();(进程级单例)
- compat这当前情况不予考虑.
- mMainThread = mainThread;
- mActivityToken = activityToken;
- mContentResolver = new ApplicationContentResolver(this, mainThread, user);
- mUser = user; (UserHandle代表设备的一个用户, 但其实目前Android基本没有启用多用户)
- ApplicatioInfo的sourceDir的设置过程:
- 前面说过, 在AMS这种case下,用到的ApplicationInfo是PackageManagerService中的mAndroidApplication.
- 而mAndroidApplication是在scanPackageLI(…)中遇到包名为”android”的Package时取的pkg.applicationInfo.
- 上面的pkg的类型为PackageParser.Package
- scanPackageLI(PackageParser.Package, …)可以由scanPackageLI(File scanFile,… )调起来.
- 该函数的pkg是这样得到的: final PackageParser.Package pkg = pp(PackageParser pp = new PackageParser(scanPath)).parsePackage(scanFile, scanPath(String scanPath = scanFile.getPath()), mMetrics, parseFlags);
- 上面这一步生成的pkg并没有设置sourceDir
- 而是sourceDir是由setApplicationInfoPaths(pkg, codePath, resPath)设置的, 该函数设置了PackageParser.Packaged的applicationInfo的sourceDir和publicSourceDir
- 不过上面用到的codePath = pkg.mScanPath, resPath也参考了pkg的mScanPath.
- 而mScanPath则确实是在PackageParser的parsePackage(…)中被设置的:
- mArchiveSourcePath = sourceFile.getPath();
- pkg.mScanPath = mArchiveSourcePath;
- 而scanPackageLI(File scanFile,… )进一步由scanDirLI(File dir, int flags, int scanMode, long currentTime)调用.
- scanDirLI会在PackagerManagerService构造时调用若干次来扫描若干个目录:
- frameworkDir: new File(Environment.getRootDirectory(), “framework”);
- privilegedAppDir: new File(Environment.getRootDirectory(), “priv-app”)
- systemAppDir: new File(Environment.getRootDirectory(), “app”)
- vendorAppDir: new File(“/vendor/app”)
- mAppInstallDir mAppInstallDir = new File(dataDir, “app”);
- mDrmAppPrivateInstallDir: new File(dataDir, “app-private”)
- 上面的Environment.getRootDirectory()得到的一般是”/system”目录.
- 上述目录存放了大量的apk文件.
- 在该case中, scanFile就是”framework-res.apk”, sourceDir也就是/system/framework/framework-res.apk, 而得到Resources对象时的ResDir也就是这个路径
Android ActivityManagerService 笔记(1)
最新推荐文章于 2021-05-25 20:43:44 发布