在之前的分析中,重点一直是分析打开应用的时候创建的AssetManager,在查看log的时候,可以看到另外一个AssetManager对象,这个对象创建后有对其进行回收操作
05-02 04:21:22.852: D/AssetManager(18460): =====CCAM decRefsLocked,
05-02 04:21:22.852: D/AssetManager(18460): =====CCAM if (mNumRefs == 0), destroy(),mstrPath=/mnt/asec/com.UCMobile-2/base.apk, iNum=302325,this=android.content.res.AssetManager@6280cad
05-02 04:21:22.853: D/AssetManager(18460): ===== begin =====
05-02 04:21:22.853: D/AssetManager(18460): android.content.res.AssetManager.decRefsLocked(AssetManager.java:1120)
05-02 04:21:22.853: D/AssetManager(18460): android.content.res.AssetManager.close(AssetManager.java:165)
05-02 04:21:22.853: D/AssetManager(18460): libcore.io.IoUtils.closeQuietly(IoUtils.java:56)
05-02 04:21:22.853: D/AssetManager(18460): android.content.pm.PackageParser.parseApkLite(PackageParser.java:1338)
05-02 04:21:22.853: D/AssetManager(18460): android.content.pm.PackageParser.parseClusterPackageLite(PackageParser.java:744)
05-02 04:21:22.853: D/AssetManager(18460): android.content.pm.PackageParser.parsePackageLite(PackageParser.java:717)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.pm.PackageManagerService$AsecInstallArgs.getAllCodePaths(PackageManagerService.java:13169)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.pm.PackageManagerService$AsecInstallArgs.doPostDeleteLI(PackageManagerService.java:13194)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.pm.PackageManagerService.deletePackageX(PackageManagerService.java:14618)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.pm.PackageManagerService.-wrap11(PackageManagerService.java)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.pm.PackageManagerService$12.run(PackageManagerService.java:14485)
05-02 04:21:22.853: D/AssetManager(18460): android.os.Handler.handleCallback(Handler.java:815)
05-02 04:21:22.853: D/AssetManager(18460): android.os.Handler.dispatchMessage(Handler.java:104)
05-02 04:21:22.853: D/AssetManager(18460): android.os.Looper.loop(Looper.java:207)
05-02 04:21:22.853: D/AssetManager(18460): android.os.HandlerThread.run(HandlerThread.java:61)
05-02 04:21:22.853: D/AssetManager(18460): com.android.server.ServiceThread.run(ServiceThread.java:46)
05-02 04:21:22.853: W/assetJNI(18460): =====jni Destroying AssetManager 0x7f5d660d40 for Java object 0x7f66af38c4
05-02 04:21:22.853: W/assetJNI(18460): =====jni L2178 delete am; am=0x7f5d660d40
查看调用流程
以卸载sd卡里的应用为例,在卸载的时候,调用到
AsecInstallArgs里的
private List<String> getAllCodePaths() {
final File codeFile = new File(getCodePath());
if (codeFile != null && codeFile.exists()) {
try {
final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
return pkg.getAllCodePaths();
} catch (PackageParserException e) {
// Ignored; we tried our best
}
}
return Collections.EMPTY_LIST;
}
查看PackageParser.parsePackageLite(codeFile, 0);
public static PackageLite parsePackageLite(File
packageFile, int flags)
throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackageLite(packageFile, flags);
} else {
return parseMonolithicPackageLite(packageFile, flags);
}
}
private static PackageLite parseClusterPackageLite(File
packageDir, int flags)
throws PackageParserException {
final File[] files = packageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"No packages found in split");
}
String packageName = null;
int versionCode = 0;
final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
for (File file : files) {
if (isApkFile(file)) {
final ApkLite lite = parseApkLite(file, flags);
查看parseApkLite
public static ApkLite parseApkLite(File
apkFile, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
AssetManager assets = null;
XmlResourceParser parser = null;
try {
assets = new AssetManager();
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
int cookie = assets.addAssetPath(apkPath);
if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Failed to parse " + apkPath);
}
final DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
final Resources res = new Resources(assets, metrics, null);
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Signature[] signatures;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package(null);
collectCertificates(tempPkg, apkFile, 0);
signatures = tempPkg.mSignatures;
} else {
signatures = null;
}
final AttributeSet attrs = parser;
return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
} catch (XmlPullParserException | IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to parse " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
}
}
在这里 IoUtils.closeQuietly(assets);进行了释放