在本章开始之前,我们应该都安装过应用。
每次安装应用的出发点都是有一个检查权限的弹框,那么我们就冲这个弹框入手.
安装应用一定首先要把apk的路径传过来,
系统安装应用信息如下:
act=android.intent.action.VIEW
dat=file:///storage/emulated/0/activityTest.apk
typ=application/vnd.android.package-archive
flg=0x17000000
cmp=com.android.packageinstaller/.PackageInstallerActivity
Step 1 : PackageInstallerActivity.java
protected void onCreate(Bundle icicle) { super.onCreate(icicle); mPm = getPackageManager(); mInstaller = mPm.getPackageInstaller(); mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); final Intent intent = getIntent(); if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) { //5.1的原生是没有检查permission的 } else { mSessionId = -1; mPackageURI = intent.getData(); //这里获取到安装包的Uri路径 mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI); mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER); } final String scheme = mPackageURI.getScheme(); ...... final PackageUtil.AppSnippet as; if ("package".equals(mPackageURI.getScheme())) { mInstallFlowAnalytics.setFileUri(false); try { mPkgInfo = mPm.getPackageInfo(mPackageURI.getSchemeSpecificPart(), PackageManager.GET_PERMISSIONS | PackageManager.GET_UNINSTALLED_PACKAGES); } catch (NameNotFoundException e) { } if (mPkgInfo == null) { Log.w(TAG, "Requested package " + mPackageURI.getScheme() + " not available. Discontinuing installation"); showDialogInner(DLG_PACKAGE_ERROR); setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK); mInstallFlowAnalytics.setPackageInfoObtained(); mInstallFlowAnalytics.setFlowFinished( InstallFlowAnalytics.RESULT_FAILED_PACKAGE_MISSING); return; } as = new PackageUtil.AppSnippet(mPm.getApplicationLabel(mPkgInfo.applicationInfo), mPm.getApplicationIcon(mPkgInfo.applicationInfo)); } else { mInstallFlowAnalytics.setFileUri(true); final File sourceFile = new File(mPackageURI.getPath()); //拿到文件 PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile); //解析,这里其实就已经拿到了Apk的所有信息了,包括resource里面的所有资源,由于这里拿只是为了显示,所以后面还会不断的来拿这些信息 mPkgInfo = PackageParser.generatePackageInfo(parsed, null, //拿到整个安装包的信息 PackageManager.GET_PERMISSIONS, 0, 0, null, new PackageUserState()); mPkgDigest = parsed.manifestDigest; as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile); //这里只是提取icon和lable供我们显示使用 } ..... }
Step 2 : PackageInstallerActivity.java //当可以安装的时候,我们点击确定流程如下:
public void onClick(View v) {
if (v == mOk) {
if (mOkCanInstall || mScrollView == null) {
mInstallFlowAnalytics.setInstallButtonClicked();
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
// We're only confirming permissions, so we don't really know how the
// story ends; assume success.
mInstallFlowAnalytics.setFlowFinishedWithPackageManagerResult(
PackageManager.INSTALL_SUCCEEDED);
} else {
// Start subactivity to actually install the application
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo); //将applicationInfo传过去,这个里面有apk的信息
newIntent.setData(mPackageURI); //路径穿过去,这个apk的路径是整个流程的关键。
newIntent.setClass(this, InstallAppProgress.class);
newIntent.putExtra(InstallAppProgress.EXTRA_MANIFEST_DIGEST, mPkgDigest);
newIntent.putExtra(
InstallAppProgress.EXTRA_INSTALL_FLOW_ANALYTICS, mInstallFlowAnalytics);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (mOriginatingURI != null) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
}
if (mReferrerURI != null) {
newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
}
if (mOriginatingUid != VerificationParams.NO_UID) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
}
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
installerPackageName);
}
if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
}
if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
startActivity(newIntent); //从这里我们可以看到,我们会将所有有用的信息都传给InstallAppProgress的Activity,来进行下一步操作。
}
finish();
} else {
mScrollView.pageScroll(View.FOCUS_DOWN);
}
} else if(v == mCancel) {
// Cancel and finish
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, false);
}
mInstallFlowAnalytics.setFlowFinished(
InstallFlowAnalytics.RESULT_CANCELLED_BY_USER);
finish();
}
}
Step 3 : InstallAppProgress.java
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent intent = getIntent();
mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mInstallFlowAnalytics = intent.getParcelableExtra(EXTRA_INSTALL_FLOW_ANALYTICS);
mInstallFlowAnalytics.setContext(this);
mPackageURI = intent.getData(); //这里时apk的路径
final String scheme = mPackageURI.getScheme();
if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) {
mInstallFlowAnalytics.setFlowFinished(
InstallFlowAnalytics.RESULT_FAILED_UNSUPPORTED_SCHEME);
throw new IllegalArgumentException("unexpected scheme " + scheme);
}
initView();
}
public void initView() {
......//中间的一些view的初始化与数据的获取
if ("package".equals(mPackageURI.getScheme())) {
try {
pm.installExistingPackage(mAppInfo.packageName);
observer.packageInstalled(mAppInfo.packageName,
PackageManager.INSTALL_SUCCEEDED);
} catch (PackageManager.NameNotFoundException e) {
observer.packageInstalled(mAppInfo.packageName,
PackageManager.INSTALL_FAILED_INVALID_APK);
}
} else {
pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
installerPackageName, verificationParams, null); //这里进行安装apk的地方
}
}
public void installPackageWithVerificationAndEncryption(Uri packageURI,
PackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
encryptionParams);
}
private void installCommon(Uri packageURI,
PackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
if (!"file".equals(packageURI.getScheme())) {
throw new UnsupportedOperationException("Only file:// URIs are supported");
}
if (encryptionParams != null) {
throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
}
final String originPath = packageURI.getPath();
try {
mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName,
verificationParams, null);
} catch (RemoteException ignored) {
}
}
Step 6 : PackageManagerService.java
public void installPackage(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride) {
installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams,
packageAbiOverride, UserHandle.getCallingUserId());
}
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
final int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { //多用户权限管理
try {
if (observer != null) {
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
}
} catch (RemoteException re) {
}
return;
}
if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
installFlags |= PackageManager.INSTALL_FROM_ADB; //adb 安装流程与正式流程分开
} else {
// Caller holds INSTALL_PACKAGES permission, so we're less strict
// about installerPackageName.
installFlags &= ~PackageManager.INSTALL_FROM_ADB;
installFlags &= ~PackageManager.INSTALL_ALL_USERS;
}
UserHandle user;
if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
} else {
user = new UserHandle(userId);
}
verificationParams.setInstallerUid(callingUid);
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, observer, installFlags,
installerPackageName, verificationParams, user, packageAbiOverride);
mHandler.sendMessage(msg); //这里将信息放到InstallParams里,通过Handler来依次执行操作。
}
public void handleMessage(Message msg) {
try {
doHandleMessage(msg);
} finally {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}
执行INIT_COPY 消息。
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj; //这个的类型是InstallParams在Step 6中可以看到
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
// If a bind was already initiated we dont really
// need to do anything. The pending install
// will be processed later on.
if (!mBound) { //这个值是在connectToService()中设置为true的,这里做的就是初始化server
// If this is the only one pending we might
// have to bind to the service again.
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
return;
} else {
// Once we bind to the service, the first
// pending request will be processed.
mPendingInstalls.add(idx, params); //这里放进去的信息,之后就等待service绑定成功之后,我们进行下一步操作。
}
} else {
mPendingInstalls.add(idx, params);
// Already bound to the service. Just make
// sure we trigger off processing the first request.
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND); //可以看到如果已经连接成功,并且是第一个数据,(这种情况是很少会发生的,这里应该只是为了容错处理,正常的流程是在Step 8中)直接进行下一步
}
}
break;
}
private boolean connectToService() {
if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
" DefaultContainerService");
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
if (mContext.bindServiceAsUser(service, mDefContainerConn,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { //在连接的时候,这个service并没有做什么,只是一个启动和bind的过程。
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return false;
}
Step 8 :PackageManagerService$PackageHandler
下面我们来看绑定service成功的时候,
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
IMediaContainerService imcs =
IMediaContainerService.Stub.asInterface(service);
mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs)); //这里是常规的进行下一步操作的地方。Bound里是操作的地方,继续跟踪就会发现每次执行完mPendingInstalls里的所有事件之后,就会unbind这个service,
}
public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
};
Step 9 :PackageManagerService$PackageHandler
void doHandleMessage(Message msg) { switch (msg.what) { case MCS_BOUND: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound"); if (msg.obj != null) { //这个是在Step 8中传过来的,所以正常情况肯定是不会是null的 mContainerService = (IMediaContainerService) msg.obj; } if (mContainerService == null) { // Something seriously wrong. Bail out Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { // Indicate service bind error params.serviceError(); } mPendingInstalls.clear(); } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); //在Step 6中我们可以知道,这个是InstallParams类型。 if (params != null) { if (params.startCopy()) { // We are done... look for more work or to // go idle. if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..."); // Delete pending install if (mPendingInstalls.size() > 0) { mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { if (mBound) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND"); removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); // Unbind after a little delay, to avoid // continual thrashing. sendMessageDelayed(ubmsg, 10000); } } else { // There are more pending requests in queue. // Just post MCS_BOUND message to trigger processing // of next pending install. if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work"); mHandler.sendEmptyMessage(MCS_BOUND); } } } } else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; }
private abstract class HandlerParams { final boolean startCopy() { //进入到父类的方法中, boolean res; try { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); if (++mRetries > MAX_RETRIES) { Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); mHandler.sendEmptyMessage(MCS_GIVE_UP); handleServiceError(); return false; } else { handleStartCopy(); //调回到InstallParams res = true; } } catch (RemoteException e) { if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT"); mHandler.sendEmptyMessage(MCS_RECONNECT); res = false; } handleReturnCode(); //到Step 22中查看。 return res; } }
Step 10 :PackageManagerService$InstallParams
public void handleStartCopy() throws RemoteException { .....//省略的是一些权限检查与 if(mInstaller.freeCache()){}这里是通过socket连接到installd的驱动进行释放cache的,保证我们可以正常安装 ...... final InstallArgs args = createInstallArgs(this); //这里是在Step 11中创建的,这里如果不是安装在sd卡上的话,则会返回FileInstallArgs mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { ...... //这里则是针对所将要发送的广播做一些数据的填充。而且在这里又一次调用了PackageParse解析apk,这里不再重复了, final PackageVerificationState verificationState = new PackageVerificationState( requiredUid, args); //这里将我们的args放入mPendingVerification中,在Step 12中会取出使用 mPendingVerification.append(verificationId, verificationState); ........ if (ret == PackageManager.INSTALL_SUCCEEDED && mRequiredVerifierPackage != null) { /* * Send the intent to the required verification agent, * but only start the verification timeout after the * target BroadcastReceivers have run. */ verification.setComponent(requiredVerifierComponent); mContext.sendOrderedBroadcastAsUser(verification, getUser(), android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final Message msg = mHandler .obtainMessage(CHECK_PENDING_VERIFICATION); msg.arg1 = verificationId; mHandler.sendMessageDelayed(msg, getVerificationTimeout());//当广播被接收之后,会发送消息出去。放出去之后,进入到Step 12中 } }, null, 0, null, null); /* * We don't want the copy to proceed until verification * succeeds, so null out this field. */ mArgs = null; } } else { /* * No package verification is enabled, so immediately start * the remote call to initiate copy using temporary file. */ ret = args.copyApk(mContainerService, true); } } mRet = ret; }
Step 11 : PackageManagerService$InstallParams
Step 12 : PackageManagerService$PackageHandlerprivate InstallArgs createInstallArgs(InstallParams params) { if (installOnSd(params.installFlags) || params.isForwardLocked()) { return new AsecInstallArgs(params); } else { return new FileInstallArgs(params); } }
case CHECK_PENDING_VERIFICATION: {
final int verificationId = msg.arg1;
final PackageVerificationState state = mPendingVerification.get(verificationId);
if ((state != null) && !state.timeoutExtended()) {
final InstallArgs args = state.getInstallArgs(); //这里取出Step 11中放入的值,
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
mPendingVerification.remove(verificationId);
int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
Slog.i(TAG, "Continuing with installation of " + originUri);
state.setVerifierResponse(Binder.getCallingUid(),
PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_ALLOW,
state.getInstallArgs().getUser());
try {
ret = args.copyApk(mContainerService, true); //这里是开始复制apk的过程,之前已经检查过,这个
} catch (RemoteException e) {
Slog.e(TAG, "Could not contact the ContainerService");
}
} else {
broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_REJECT,
state.getInstallArgs().getUser());
}
processPendingInstall(args, ret);
mHandler.sendEmptyMessage(MCS_UNBIND);
}
break;
}
Step 13 : PackageManagerService$FileInstallArgs
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { if (origin.staged) { Slog.d(TAG, origin.file + " already staged; skipping copy"); codeFile = origin.file; resourceFile = origin.file; return PackageManager.INSTALL_SUCCEEDED; } try { final File tempDir = mInstallerService.allocateInternalStageDirLegacy(); //这里就是获取路径的地方。//data/app/vmdl***.tmp这里在 5.1是一个废弃的接口,所以这里有点疑惑,如果哪位发现这里的流程有问题,请及时沟通。这里建立的时候权限是755后面会改成644. codeFile = tempDir; //这里copyFile很重要,以后的文件都会拷贝到这里。 resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { //这个将会在Step 15中回调使用。 @Override public ParcelFileDescriptor open(String name, int mode) throws RemoteException { //在Step15中可以知道这个name : base.apk if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid filename: " + name); } try { final File file = new File(codeFile, name); final FileDescriptor fd = Os.open(file.getAbsolutePath(), O_RDWR | O_CREAT, 0644); Os.chmod(file.getAbsolutePath(), 0644); return new ParcelFileDescriptor(fd); } catch (ErrnoException e) { throw new RemoteException("Failed to open: " + e.getMessage()); } } }; int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); // 进入到Step 14中, if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package"); return ret; } final File libraryRoot = new File(codeFile, LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(codeFile); ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, abiOverride); } catch (IOException e) { //这里是拷贝.so到lib文件夹,并且会根据不同cpu来建立不同文件夹 Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } finally { IoUtils.closeQuietly(handle); } return ret; }
Step 13.1 : PackageInstallerService.javapublic File allocateInternalStageDirLegacy() throws IOException { synchronized (mSessions) { try { final int sessionId = allocateSessionIdLocked(); mLegacySessions.put(sessionId, true); final File stageDir = buildInternalStageDir(sessionId); prepareInternalStageDir(stageDir); return stageDir; } catch (IllegalStateException e) { throw new IOException(e); } } }
private File buildInternalStageDir(int sessionId) { return new File(mStagingDir, "vmdl" + sessionId + ".tmp"); }
Step 14 :DefaultContainerService.javaStep 15 : DefaultContainerService.java@Override public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) { if (packagePath == null || target == null) { return PackageManager.INSTALL_FAILED_INVALID_URI; } PackageLite pkg = null; try { final File packageFile = new File(packagePath); pkg = PackageParser.parsePackageLite(packageFile, 0); //这里很重要,这里已经是第三次解析了,请看Step 16: return copyPackageInner(pkg, target); } catch (PackageParserException | IOException | RemoteException e) { Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } }
private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target) throws IOException, RemoteException { copyFile(pkg.baseCodePath, target, "base.apk"); if (!ArrayUtils.isEmpty(pkg.splitNames)) { //从Step 16中,我们可以知道,这里返回的splitNames是null的,所以不会进入这里, for (int i = 0; i < pkg.splitNames.length; i++) { copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk"); } } return PackageManager.INSTALL_SUCCEEDED; }
private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName) throws IOException, RemoteException { Slog.d(TAG, "Copying " + sourcePath + " to " + targetName); InputStream in = null; OutputStream out = null; try { in = new FileInputStream(sourcePath); out = new ParcelFileDescriptor.AutoCloseOutputStream( target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); Streams.copy(in, out); //可以看到这里是将apk拷贝到临时文件里:/data/app/vmdl***.tmp/base.apk</span> } finally { IoUtils.closeQuietly(out); IoUtils.closeQuietly(in); } }
Step 16 : PackageParser.javapublic static PackageLite parsePackageLite(File packageFile, int flags) throws PackageParserException { if (packageFile.isDirectory()) { //这里会看是否是路径,我们解析apk的时候,传的都是文件。 return parseClusterPackageLite(packageFile, flags); } else { return parseMonolithicPackageLite(packageFile, flags); } }
Step 17 : PackageParser.javaprivate static PackageLite parseMonolithicPackageLite(File packageFile, int flags) throws PackageParserException { final ApkLite baseApk = parseApkLite(packageFile, flags); final String packagePath = packageFile.getAbsolutePath(); return new PackageLite(packagePath, baseApk, null, null, null);//baseApk相当于一个轻量级的apk信息实例,这里就相当于比轻量级略多信息的实例了, }
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); //这里是将apk的path添加到AssetManager中. 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); //这里将asset放到Resources中,我们知道所有的资源文件都是通过资源文件获取到的,这个返回的res其实就可以拿到我们的所有资源了,//R.layout.xxxx; parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); //这里会解析AndroidManifest,由于AssetManager的大部分方法都是在Native中完成,请参考Step 18。这里返回的parse拥有AndroidManifest中的解析信息。 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); //Step 20 中获取返回满载信息的ApkLite对象 } 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); } }
Step 18 : AssetManager.javaStep 19 : android_util_AssetManager.cpppublic final XmlResourceParser openXmlResourceParser(int cookie, String fileName) throws IOException { XmlBlock block = openXmlBlockAsset(cookie, fileName); XmlResourceParser rp = block.newParser(); block.close(); return rp; }
/*package*/ final XmlBlock openXmlBlockAsset(String fileName) throws IOException { return openXmlBlockAsset(0, fileName); }
/*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName) throws IOException { synchronized (this) { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } long xmlBlock = openXmlAssetNative(cookie, fileName); if (xmlBlock != 0) { XmlBlock res = new XmlBlock(this, xmlBlock); incRefsLocked(res.hashCode()); return res; } } throw new FileNotFoundException("Asset XML file: " + fileName); }
static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz, jint cookie, jstring fileName) { AssetManager* am = assetManagerForJavaObject(env, clazz); if (am == NULL) { return 0; } ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz); ScopedUtfChars fileName8(env, fileName); if (fileName8.c_str() == NULL) { return 0; } int32_t assetCookie = static_cast<int32_t>(cookie); Asset* a = assetCookie ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER) : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie); if (a == NULL) { jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str()); return 0; } const DynamicRefTable* dynamicRefTable = am->getResources().getDynamicRefTableForCookie(assetCookie); ResXMLTree* block = new ResXMLTree(dynamicRefTable); status_t err = block->setTo(a->getBuffer(true), a->getLength(), true); a->close(); delete a; if (err != NO_ERROR) { jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file"); return 0; } return reinterpret_cast<jlong>(block); }
Step 20 : PackageParser.java
private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, Signature[] signatures) throws IOException, XmlPullParserException, PackageParserException { final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags); int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; int revisionCode = 0; boolean coreApp = false; boolean multiArch = false; for (int i = 0; i < attrs.getAttributeCount(); i++) { final String attr = attrs.getAttributeName(i); if (attr.equals("installLocation")) { installLocation = attrs.getAttributeIntValue(i, PARSE_DEFAULT_INSTALL_LOCATION); } else if (attr.equals("versionCode")) { versionCode = attrs.getAttributeIntValue(i, 0); } else if (attr.equals("revisionCode")) { revisionCode = attrs.getAttributeIntValue(i, 0); } else if (attr.equals("coreApp")) { coreApp = attrs.getAttributeBooleanValue(i, false); } } // Only search the tree when the tag is directly below <manifest> int type; final int searchDepth = parser.getDepth() + 1; final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) { final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags); //这里是key的解析 if (verifier != null) { verifiers.add(verifier); } } if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) { for (int i = 0; i < attrs.getAttributeCount(); ++i) { final String attr = attrs.getAttributeName(i); if ("multiArch".equals(attr)) { multiArch = attrs.getAttributeBooleanValue(i, false); break; } } } } return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode, revisionCode, installLocation, verifiers, signatures, coreApp, multiArch); }
Step 21 :PackageParser$ApkLite到这里我们已经对整个apk的拷贝过程基本了解里,下面我们在回到Step 9中,看看拷贝之后做了哪些事情。public static class ApkLite { public final String codePath; public final String packageName; public final String splitName; public final int versionCode; public final int revisionCode; public final int installLocation; public final VerifierInfo[] verifiers; public final Signature[] signatures; public final boolean coreApp; public final boolean multiArch; public ApkLite(String codePath, String packageName, String splitName, int versionCode, int revisionCode, int installLocation, List<VerifierInfo> verifiers, Signature[] signatures, boolean coreApp, boolean multiArch) { this.codePath = codePath; this.packageName = packageName; this.splitName = splitName; this.versionCode = versionCode; this.revisionCode = revisionCode; this.installLocation = installLocation; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); this.signatures = signatures; this.coreApp = coreApp; this.multiArch = multiArch; } }
Step 22 : PackageManagerService.java$InstallParams@Override void handleReturnCode() { // If mArgs is null, then MCS couldn't be reached. When it // reconnects, it will try again to install. At that point, this // will succeed. if (mArgs != null) { //这个是在Step 10中赋值的,FileInstallArgs</span> processPendingInstall(mArgs, mRet); } }
Step 23:PackageManagerService.javaprivate void processPendingInstall(final InstallArgs args, final int currentStatus) { // Queue up an async operation since the package installation may take a little while. mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); // Result object to be returned PackageInstalledInfo res = new PackageInstalledInfo(); res.returnCode = currentStatus; res.uid = -1; res.pkg = null; res.removedInfo = new PackageRemovedInfo(); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { args.doPreInstall(res.returnCode); //这里是一个如果失败了的话,会进行clean的操作,会将刚才的/data/app/vmdl***.tmp文件夹及下面的文件删掉. synchronized (mInstallLock) { installPackageLI(args, res); //进入Step 24 } args.doPostInstall(res.returnCode, res.uid); } // A restore should be performed at this point if (a) the install // succeeded, (b) the operation is not an update, and (c) the new // package has not opted out of backup participation. final boolean update = res.removedInfo.removedPackage != null; final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags; boolean doRestore = !update && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0); // Set up the post-install work request bookkeeping. This will be used // and cleaned up by the post-install event handling regardless of whether // there's a restore pass performed. Token values are >= 1. int token; if (mNextInstallToken < 0) mNextInstallToken = 1; token = mNextInstallToken++; PostInstallData data = new PostInstallData(args, res); mRunningInstalls.put(token, data); if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) { // Pass responsibility to the Backup Manager. It will perform a // restore if appropriate, then pass responsibility back to the // Package Manager to run the post-install observer callbacks // and broadcasts. IBackupManager bm = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); if (bm != null) { if (DEBUG_INSTALL) Log.v(TAG, "token " + token + " to BM for possible restore"); try { if (bm.isBackupServiceActive(UserHandle.USER_OWNER)) { bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token); } else { doRestore = false; } } catch (RemoteException e) { // can't happen; the backup manager is local } catch (Exception e) { Slog.e(TAG, "Exception trying to enqueue restore", e); doRestore = false; } } else { Slog.e(TAG, "Backup Manager not found!"); doRestore = false; } } if (!doRestore) { // No restore possible, or the Backup Manager was mysteriously not // available -- just fire the post-install work request directly. if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token); Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); mHandler.sendMessage(msg); } } }); }
Step 24:PackageManagerService.javaprivate void installPackageLI(InstallArgs args, PackageInstalledInfo res) { final int installFlags = args.installFlags; String installerPackageName = args.installerPackageName; File tmpPackageFile = new File(args.getCodePath()); boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0); boolean replace = false; final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE; // Result object to be returned res.returnCode = PackageManager.INSTALL_SUCCEEDED; if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); // Retrieve PackageSettings and parse package final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onSd ? PackageParser.PARSE_ON_SDCARD : 0); PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); final PackageParser.Package pkg; try { pkg = pp.parsePackage(tmpPackageFile, parseFlags); //这里第四次解析,但这次和在Step 14中有区别的,这个tmpPackageFile是个path,流程不同而已,最终还是一条路. } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); return; } //中间的权限检查,版本升级流程等信息省略..... if (!args.doRename(res.returnCode, pkg, oldCodePath)) { //这个命名规则很简单暴力,看Step 25 res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename"); return; } if (replace) { //如果覆盖安装、升级走replace,新安装走下面的。 replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user, installerPackageName, res); } else { installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, //进入step 27 args.user, installerPackageName, res); } synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true); } } }
Step 25 :PackageManagerService.java$FileInstallArgsStep 26 : PackageManagerService.java$FileInstallArgsboolean doRename(int status, PackageParser.Package pkg, String oldCodePath) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); return false; } else { final File beforeCodeFile = codeFile; final File afterCodeFile = getNextCodePath(pkg.packageName); //从Step 26中可以看到,这里返回的就是packagename-n.apk这个n是从1一直加的知道文件不存在。 Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile); try { Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath()); //改完之后,就变成了packagename-n.apk</span> } catch (ErrnoException e) { Slog.d(TAG, "Failed to rename", e); return false; } if (!SELinux.restoreconRecursive(afterCodeFile)) { Slog.d(TAG, "Failed to restorecon"); return false; } // Reflect the rename internally codeFile = afterCodeFile; resourceFile = afterCodeFile; // Reflect the rename in scanned details pkg.codePath = afterCodeFile.getAbsolutePath(); pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile, pkg.baseCodePath); pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile, pkg.splitCodePaths); // Reflect the rename in app info pkg.applicationInfo.setCodePath(pkg.codePath); pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath); pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths); pkg.applicationInfo.setResourcePath(pkg.codePath); pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath); pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths); return true; } }
Step 27 : PackageManagerService.javaprivate File getNextCodePath(String packageName) { int suffix = 1; File result; do { result = new File(mAppInstallDir, packageName + "-" + suffix); suffix++; } while (result.exists()); return result; }
private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user, String installerPackageName, PackageInstalledInfo res) { // Remember this for later, in case we need to rollback this install String pkgName = pkg.packageName; if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg); boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists(); //这个获取的就是data/data/packagename/路径 synchronized(mPackages) { if (mSettings.mRenamedPackages.containsKey(pkgName)) { // A package with the same name is already installed, though // it has been renamed to an older name. The package we // are trying to install should be installed as an update to // the existing one, but that has not been requested, so bail. res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling package running as " + mSettings.mRenamedPackages.get(pkgName)); return; } if (mPackages.containsKey(pkgName)) { //这时候,我们新安装的mPackages中还没有我们的包对应的信息 // Don't allow installation over an existing package with the same name. res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName + " without first uninstalling."); return; } } try { PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags, System.currentTimeMillis(), user); //在这里将我们的包添加到mPackage中,查看Step 28 updateSettingsLI(newPackage, installerPackageName, null, null, res); //这里是更新文件的操作,参考Step 33 // delete the partially installed application. the data directory will have to be // restored if it was already existing if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { // remove package from internal structures. Note that we want deletePackageX to // delete the package data and cache directories that it created in // scanPackageLocked, unless those directories existed before we even tried to // install. deletePackageLI(pkgName, UserHandle.ALL, false, null, null, dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0, res.removedInfo, true); } } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); } }
Step 28 : PackageManagerService.javaStep 29 : PackageManagerService.javaprivate PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) { parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY; } final PackageParser.Package pkg; try { pkg = pp.parsePackage(scanFile, parseFlags); //这里已经是第五次解析了。流程都是一样的 } catch (PackageParserException e) { throw PackageManagerException.from(e); } PackageSetting ps = null; PackageSetting updatedPkg; ..... //这里都是一些判断和升级的操作,防止太凌乱,我们关注新安装这部分。 // Set application objects path explicitly. pkg.applicationInfo.setCodePath(pkg.codePath); pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath); pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths); pkg.applicationInfo.setResourcePath(resourcePath); pkg.applicationInfo.setBaseResourcePath(baseResourcePath); pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths); // Note that we invoke the following method only if we are about to unpack an application PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); //进入Step 29中 /* * If the system app should be overridden by a previously installed * data, hide the system app now and let the /data/app scan pick it up * again. */ if (shouldHideSystemApp) { synchronized (mPackages) { /* * We have to grant systems permissions before we hide, because * grantPermissions will assume the package update is trying to * expand its permissions. */ grantPermissionsLPw(pkg, true, pkg.packageName); mSettings.disableSystemPackageLPw(pkg.packageName); } } return scannedPkg; }
Step 30 :PackageManagerService.javaprivate PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { boolean success = false; try { final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags, currentTime, user); success = true; return res; } finally { if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) { removeDataDirsLI(pkg.packageName); } } }
Step 31 :Settings.javaprivate PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { final File scanFile = new File(pkg.codePath); ...... // Just create the setting, don't add it yet. For already existing packages // the PkgSetting exists already and doesn't have to be created. pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags, user, false); 这个方法比较大,先看我们关注的,进入到Step 31: ...... return pkg; }
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, int pkgFlags, UserHandle user, boolean add) { final String name = pkg.packageName; PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi, pkg.mVersionCode, pkgFlags, user, add, true /* allowInstall */); return p; }
Step 32 :Settings.javaprivate PackageSetting getPackageLPw(String name, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) { PackageSetting p = mPackages.get(name); UserManagerService userManager = UserManagerService.getInstance(); ...... if (p == null) { if (origPackage != null) { ...... } else { p = new PackageSetting(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, null /* cpuAbiOverrideString */, vc, pkgFlags); p.setTimeStamp(codePath.lastModified()); p.sharedUser = sharedUser; ...... if (add) { //这个在Step 30中可以看到是true // Finish adding new package by adding it and updating shared // user preferences addPackageSettingLPw(p, name, sharedUser); } } else { } return p; }
Step 33 :PackageManagerService.javaprivate void addPackageSettingLPw(PackageSetting p, String name, SharedUserSetting sharedUser) { mPackages.put(name, p); //这里将我们的内容加到mPackages中, if (sharedUser != null) { if (p.sharedUser != null && p.sharedUser != sharedUser) { PackageManagerService.reportSettingsProblem(Log.ERROR, "Package " + p.name + " was user " + p.sharedUser + " but is now " + sharedUser + "; I am not changing its files so it will probably fail!"); p.sharedUser.removePackage(p); } else if (p.appId != sharedUser.userId) { PackageManagerService.reportSettingsProblem(Log.ERROR, "Package " + p.name + " was user id " + p.appId + " but is now user " + sharedUser + " with id " + sharedUser.userId + "; I am not changing its files so it will probably fail!"); } sharedUser.addPackage(p); p.sharedUser = sharedUser; p.appId = sharedUser.userId; } }
private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res) { String pkgName = newPackage.packageName; synchronized (mPackages) { //write settings. the installStatus will be incomplete at this stage. //note that the new package setting would have already been //added to mPackages. It hasn't been persisted yet. mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE); //这里更新当前包名对应的安装状态, mSettings.writeLPr(); //这里是写文件的操作,流程比较清晰,就是先备份/data/system/package.xml然后再讲(查看Step 32)写入到里面 } if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + newPackage.codePath); synchronized (mPackages) { updatePermissionsLPw(newPackage.packageName, newPackage, UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0)); // For system-bundled packages, we assume that installing an upgraded version // of the package implies that the user actually wants to run that new code, // so we enable the package. if (isSystemApp(newPackage)) { // NB: implicit assumption that system package upgrades apply to all users if (DEBUG_INSTALL) { Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName); } PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { if (res.origUsers != null) { for (int userHandle : res.origUsers) { ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userHandle, installerPackageName); } } // Also convey the prior install/uninstall state if (allUsers != null && perUserInstalled != null) { for (int i = 0; i < allUsers.length; i++) { if (DEBUG_INSTALL) { Slog.d(TAG, " user " + allUsers[i] + " => " + perUserInstalled[i]); } ps.setInstalled(perUserInstalled[i], allUsers[i]); } // these install state changes will be persisted in the // upcoming call to mSettings.writeLPr(). } } } res.name = pkgName; res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE); mSettings.setInstallerPackageName(pkgName, installerPackageName); res.returnCode = PackageManager.INSTALL_SUCCEEDED; //to update install status mSettings.writeLPr(); //这里还是更新xml这里的状态就改成安装完成了 } }
到这里就结束了,整个应用安装流程。
下面来总结一下都做了什么
1.apk移动到了指定路径/data/app/package-n.apk
2.将apk信息记录在xml中/data/system/packages.xml
3.将apk的信息存到了mPackages中,每次查询apk信息,可以直接到这里来查
下面我们随便找一个case来验证一下我们的结论吧,加入我们想要查找apk的应用信息
@Override public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info"); // writer synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); //这个mPacakges是我们记录下来的。 if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getApplicationInfo " + packageName + ": " + p); if (p != null) { PackageSetting ps = mSettings.mPackages.get(packageName); //ps使我们存下来的信息 if (ps == null) return null; // Note: isEnabledLP() does not apply here - always return info return PackageParser.generateApplicationInfo( p, flags, ps.readUserState(userId), userId); //我们可以根据这个信息来获取应用信息, } if ("android".equals(packageName)||"system".equals(packageName)) { return mAndroidApplication; } if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { return generateApplicationInfoFromSettingsLPw(packageName, flags, userId); } } return null; }
End