【Android】点击应用进而打开base.apk的调用流程再分析

来源:互联网 发布:女生做春梦 知乎 编辑:程序博客网 时间:2024/05/16 05:55


点击一个应用的时候,会加载其对应的base.apk,我们在AssetManager类的addAssetPath方法中添加堆栈打印,

其调用堆栈为

android.content.res.AssetManager.addAssetPath(AssetManager.java:653)

 android.app.ResourcesManager.getTopLevelResources(ResourcesManager.java:221)

 android.app.ActivityThread.getTopLevelResources(ActivityThread.java:1854)

 android.app.LoadedApk.getResources(LoadedApk.java:558)

 android.app.ContextImpl.<init>(ContextImpl.java:1884)

 android.app.ContextImpl.createPackageContextAsUser(ContextImpl.java:1733)

 android.app.ContextImpl.createPackageContextAsUser(ContextImpl.java:1718)

 com.android.server.AttributeCache.get(AttributeCache.java:114)

 com.android.server.am.ActivityRecord.<init>(ActivityRecord.java:564)com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1763)

com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:1153)

com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:4271)

 com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:4258)

 android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:168)

 com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2703)

 

分析这个堆栈信息,我们来追根溯源的查看AssetManager对象的创建过程。

第一次打开应用的时候,调到ActivityManagerService的startActivityAsUser方法,

后来调到com.android.server.am.ActivityRecord.<init>(ActivityRecord.java:564)

564 AttributeCache.Entry ent = AttributeCache.instance().get(packageName,

565              realTheme,com.android.internal.R.styleable.Window, userId);

继续调用

com.android.server.AttributeCache.get(AttributeCache.java:114)

查看AttributeCache.java

112 Context context;

113 try {

114     context =mContext.createPackageContextAsUser(packageName, 0,

115             new UserHandle(userId));

116     if (context == null) {

117         return null;

118     }

119 } catch (PackageManager.NameNotFoundExceptione) {

120     return null;

121 }

122 pkg = new Package(context);

123 mPackages.put(packageName, pkg);

在这里,mPackages是一个map,其定义为

        private final WeakHashMap<String,Package> mPackages =

            newWeakHashMap<String, Package>();

在Android 7上,修改为了

    private finalArrayMap<String, WeakReference<Package>> mPackages = newArrayMap<>();

 

在114行,变量context指向了mContext.createPackageContextAsUser(packageName, 0, newUserHandle(userId));的返回值

在122行对context进行了引用。

 

114行调用到android.app.ContextImpl.createPackageContextAsUser(ContextImpl.java:1718)

继续调用到

android.app.ContextImpl.createPackageContextAsUser(ContextImpl.java:1733)

查看ContextImpl.java

1733     ContextImpl c = new ContextImpl(this,mMainThread, pi, mActivityToken,

1734   user, restricted, mDisplay, null,Display.INVALID_DISPLAY, themePackageName);

 

1733行又调用到

android.app.ContextImpl.<init>(ContextImpl.java:1884)

查看ContextImpl.java

1884         Resources resources =packageInfo.getResources(mainThread);

1906         mResources = resources;

新创建的ContextImpl对象的成员变量mResources对resources进行了引用。

 

1884行继续调用

android.app.LoadedApk.getResources(LoadedApk.java:558)

android.app.ActivityThread.getTopLevelResources(ActivityThread.java:1854)

android.app.ResourcesManager.getTopLevelResources(ResourcesManager.java:221)

查看ResourcesManager.java

211         AssetManager assets = newAssetManager();

 

218         // already.

219         if (resDir != null) {

220  

221             if (assets.addAssetPath(resDir) ==0) {

222                 return null;

223             }

224         }

 

301         r = new Resources(assets, dm, config,compatInfo);

 

319             return r;

 

终于,找到了AssetManager创建的地方了,然后创建了C++层的AssetManager对象,再调用addAssetPath方法加载了base.apk

在Resources.java中有

   public Resources(AssetManager assets, DisplayMetrics metrics,Configuration config,  CompatibilityInfocompatInfo) {

        mAssets = assets;

        mMetrics.setToDefaults();

        if (compatInfo != null) {

            mCompatibilityInfo = compatInfo;

        }

        updateConfiguration(config, metrics);

        assets.recreateStringBlocks();//Modified for ThemeManager

   }

Resources中的mAssets对新创建的AssetManager对象进行了引用