文章目录
- 是ActivityThread中进行四大组件等启动过程中的重要中间变量
- LoadedApk对象是APK文件在内存中的表示。 Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service等组件的信息我们都可以通过此对象获取。
一、LoadedApk的构建函数和成员变量
- 重要的成员变量
- ActivityThread mActivityThread
- ApplicationInfo mApplicationInfo;
- String mPackageName;
- ClassLoader mBaseClassLoader;
- 以及各种资源路径地址
- 重要方法
- 生成Application
- Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation)
- Application makeApplication(boolean forceDefaultAppClass,
- 生成Resource
- getResources(ActivityThread mainThread)
- 实质上,最后是委托ResourceManager去生成的
- 生成Application
public final class LoadedApk {
private static final String TAG = "LoadedApk";
private final ActivityThread mActivityThread;
private ApplicationInfo mApplicationInfo;
final String mPackageName;
private final String mAppDir;
private final String mResDir;
private final String[] mSplitAppDirs;
private final String[] mSplitResDirs;
private final String[] mOverlayDirs;
private final String[] mSharedLibraries;
private final String mDataDir;
private final String mLibDir;
private final File mDataDirFile;
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
private final boolean mRegisterPackage;
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Resources mResources;
private ClassLoader mClassLoader;
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
final int myUid = Process.myUid();
aInfo = adjustNativeLibraryPaths(aInfo);
mActivityThread = activityThread;
mApplicationInfo = aInfo;
mPackageName = aInfo.packageName;
mAppDir = aInfo.sourceDir;
mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
mSplitAppDirs = aInfo.splitSourceDirs;
mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
mOverlayDirs = aInfo.resourceDirs;
if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
mPackageName);
}
mSharedLibraries = aInfo.sharedLibraryFiles;
mDataDir = aInfo.dataDir;
mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
mLibDir = aInfo.nativeLibraryDir;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
mRegisterPackage = registerPackage;
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
}
}
二、LoadedApk的在ActivityThread中的获取
- 在ActivityThread中大量使用了LoadedApk实例
private void handleBindApplication(AppBindData data) {
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
}
public void handleMessage(Message msg) {
case LAUNCH_ACTIVITY: {
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
} break;
}
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
}
private void handleReceiver(ReceiverData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
}
- 我们来看看ActivityThread#getPackageInfoNoCheck函数, 基于packageName会有两个缓存map,key是packagename, value是loadapk的弱引用
- 获取LoadApk时先从缓存map中获取
- 如果没有的话, 新建一个实例
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
? mBoundApplication.processName : null)
+ ")");
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
三、LoadedApk的mApplication创建Application实例
- 持有成员实例mApplication
- makeApplication: 该函数在handlebindApplication中触发
- 如果 mApplication存在则直接返回
- 如果不存在,则
- 调用Contextlmpl的静态函数,创建Context实例
- 获取Classloader并获取Application Class
- 调用Instrumentation.newApplication 初始化application
- 反射构建Application实例
- 调用Application#attach, 内部调用ContextWrapper#attachBaseContext,将Contextlmpl实例赋值给Application对象
- appContext.setOuterContext(app);给Contextlmpl实例的mOutContext赋值,实现Contextlmpl实例对四大组件实例的持有
- 调用Application的onCreate方法
public final class LoadedApk {
private Application mApplication;
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
// Rewrite the R 'constants' for all library apks.
SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
.getAssignedPackageIdentifiers();
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
if (id == 0x01 || id == 0x7f) {
continue;
}
rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
}
return app;
}
}
Application getApplication() {
return mApplication;
}
四、LoadedApk的mResources创建Resources实例
- getResources(ActivityThread mainThread)
- 如果存在mResources则直接返回
- 没有话,调用ActivityThread#getTopLevelResources新建一个
public final class LoadedApk {
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
}
return mResources;
}
public AssetManager getAssets(ActivityThread mainThread) {
return getResources(mainThread).getAssets();
}
}
- ActivityThread#getTopLevelResources
public final class ActivityThread {
/**
* Creates the top level resources for the given package.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
String[] libDirs, int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
}
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
}
- 最终还是使用了mResourcesManager去新建
- mResourcesManager这是个单例模式
ResourcesManager的创建流程我们后续在分析
五、LoadedApk的mReceivers的ArrayMap实例池
- mReceivers池的维护动作
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
public void removeContextRegistrations(Context context,
String who, String what) {
final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
mReceivers.remove(context);
if (rmap != null) {
for (int i=0; i<rmap.size(); i++) {
LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
IntentReceiverLeaked leak = new IntentReceiverLeaked(
what + " " + who + " has leaked IntentReceiver "
+ rd.getIntentReceiver() + " that was " +
"originally registered here. Are you missing a " +
"call to unregisterReceiver()?");
leak.setStackTrace(rd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onIntentReceiverLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unregisterReceiver(
rd.getIIntentReceiver());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
}
}
mUnregisteredReceivers.remove(context);
//Slog.i(TAG, "Receiver registrations: " + mReceivers);
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
mServices.remove(context);
if (smap != null) {
for (int i=0; i<smap.size(); i++) {
LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
what + " " + who + " has leaked ServiceConnection "
+ sd.getServiceConnection() + " that was originally bound here");
leak.setStackTrace(sd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onServiceConnectionLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unbindService(
sd.getIServiceConnection());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
sd.doForget();
}
}
mUnboundServices.remove(context);
//Slog.i(TAG, "Service registrations: " + mServices);
}
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
LoadedApk.ReceiverDispatcher rd = null;
if (map != null) {
rd = map.get(r);
if (rd != null) {
map.remove(r);
if (map.size() == 0) {
mReceivers.remove(context);
}
if (r.getDebugUnregister()) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
= mUnregisteredReceivers.get(context);
if (holder == null) {
holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mUnregisteredReceivers.put(context, holder);
}
RuntimeException ex = new IllegalArgumentException(
"Originally unregistered here:");
ex.fillInStackTrace();
rd.setUnregisterLocation(ex);
holder.put(r, rd);
}
rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
= mUnregisteredReceivers.get(context);
if (holder != null) {
rd = holder.get(r);
if (rd != null) {
RuntimeException ex = rd.getUnregisterLocation();
throw new IllegalArgumentException(
"Unregistering Receiver " + r
+ " that was already unregistered", ex);
}
}
if (context == null) {
throw new IllegalStateException("Unbinding Receiver " + r
+ " from Context that is no longer in use: " + context);
} else {
throw new IllegalArgumentException("Receiver not registered: " + r);
}
}
}
六、LoadedApk的mServices的ArrayMap实例池
- mServices池的维护动作
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
public void removeContextRegistrations(Context context,
String who, String what) {
final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
mReceivers.remove(context);
if (rmap != null) {
for (int i=0; i<rmap.size(); i++) {
LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
IntentReceiverLeaked leak = new IntentReceiverLeaked(
what + " " + who + " has leaked IntentReceiver "
+ rd.getIntentReceiver() + " that was " +
"originally registered here. Are you missing a " +
"call to unregisterReceiver()?");
leak.setStackTrace(rd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onIntentReceiverLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unregisterReceiver(
rd.getIIntentReceiver());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
}
}
mUnregisteredReceivers.remove(context);
//Slog.i(TAG, "Receiver registrations: " + mReceivers);
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
mServices.remove(context);
if (smap != null) {
for (int i=0; i<smap.size(); i++) {
LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
what + " " + who + " has leaked ServiceConnection "
+ sd.getServiceConnection() + " that was originally bound here");
leak.setStackTrace(sd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onServiceConnectionLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unbindService(
sd.getIServiceConnection());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
sd.doForget();
}
}
mUnboundServices.remove(context);
//Slog.i(TAG, "Service registrations: " + mServices);
}
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
public final IServiceConnection forgetServiceDispatcher(Context context,
ServiceConnection c) {
synchronized (mServices) {
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
= mServices.get(context);
LoadedApk.ServiceDispatcher sd = null;
if (map != null) {
sd = map.get(c);
if (sd != null) {
map.remove(c);
sd.doForget();
if (map.size() == 0) {
mServices.remove(context);
}
if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
= mUnboundServices.get(context);
if (holder == null) {
holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mUnboundServices.put(context, holder);
}
RuntimeException ex = new IllegalArgumentException(
"Originally unbound here:");
ex.fillInStackTrace();
sd.setUnbindLocation(ex);
holder.put(c, sd);
}
return sd.getIServiceConnection();
}
}
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
= mUnboundServices.get(context);
if (holder != null) {
sd = holder.get(c);
if (sd != null) {
RuntimeException ex = sd.getUnbindLocation();
throw new IllegalArgumentException(
"Unbinding Service " + c
+ " that was already unbound", ex);
}
}
if (context == null) {
throw new IllegalStateException("Unbinding Service " + c
+ " from Context that is no longer in use: " + context);
} else {
throw new IllegalArgumentException("Service not registered: " + c);
}
}
}