Android ActivityManagerService 笔记(1)

  1. 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的形式工作
  2. 在上面的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);
  3. 在上面的准备都完毕以后, 以thr为锁, 将thr.mReady设置为true,然后thr.notifyAll()将等待的Athread线程唤醒,继续进行其run()函数, 开始Loop().
  4. 调用m(AMS).startRunning(null(String pkg), null(String cls), null(String action), null(String data))(注意这个操作不是进行在AThread线程);
    • mStartRunning = true.
    • systemReady(null(Runnable goingCallback));
  5. 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信息
  6. 接着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);
  7. 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基本没有启用多用户)
  8. 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也就是这个路径
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值