android Framework——普通应用的安装
2021-04-26 本文已影响0人
Peakmain
由上篇文章Android Framework——AMS、PMS的启动流程我们知道apk的安装实际是PackageInstaller这个类帮我们完成的。我们都知道Android7.0之后无法使用file://的URL所以我们直接分析android 8.0的源码
1、PackageInstaller的初始化
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) {//1
nextActivity.setClass(this, PackageInstallerActivity.class);
} else {
Uri packageUri = intent.getData();
if (packageUri == null) {//此处不为空
Intent result = new Intent();
result.putExtra(Intent.EXTRA_INSTALL_RESULT,
PackageManager.INSTALL_FAILED_INVALID_URI);
setResult(RESULT_FIRST_USER, result);
nextActivity = null;
} else {
if (packageUri.getScheme().equals(SCHEME_CONTENT)) {
//判断协议是否是content,Android 7.0以上走这
nextActivity.setClass(this, InstallStaging.class);
} else {
//Android 7.0以前直接走PackageInstallerActivity
nextActivity.setClass(this, PackageInstallerActivity.class);
}
}
}
if (nextActivity != null) {
startActivity(nextActivity);
}
finish();
}
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
Override
protected void onResume() {
super.onResume();
if (mStagingTask == null) {
if (mStagedFile == null) {
try {
mStagedFile = TemporaryFileManager.getStagedFile(this);
} catch (IOException e) {
showError();
return;
}
}
mStagingTask = new StagingAsyncTask();
mStagingTask.execute(getIntent().getData());
}
}
private final class StagingAsyncTask extends AsyncTask<Uri, Void, Boolean> {
@Override
protected Boolean doInBackground(Uri... params) {
if (params == null || params.length <= 0) {
return false;
}
Uri packageUri = params[0];
try (InputStream in = getContentResolver().openInputStream(packageUri)) {
if (in == null) {
return false;
}
try (OutputStream out = new FileOutputStream(mStagedFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) >= 0) {
if (isCancelled()) {
return false;
}
out.write(buffer, 0, bytesRead);
}
}
} catch (IOException | SecurityException e) {
Log.w(LOG_TAG, "Error staging apk from content URI", e);
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean success) {
if (success) {
Intent installIntent = new Intent(getIntent());
//实际最后还是走到了PackageInstallerActivity
installIntent.setClass(InstallStaging.this, PackageInstallerActivity.class);
installIntent.setData(Uri.fromFile(mStagedFile));
installIntent
.setFlags(installIntent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivityForResult(installIntent, 0);
} else {
showError();
}
}
}
}
PackageInstallerActivity源码
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (icicle != null) {
mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
}
//获取packageManager,packageManager的最终功能是由PMS实现的
mPm = getPackageManager();
//实际是个IPackageManager,一个AIDL接口,主要用于PMS进程间通信
mIpm = AppGlobals.getPackageManager();
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
//PackageInstaller:安装,升级和删除应用
mInstaller = mPm.getPackageInstaller();
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
...
//根据Uri的Scheme进行预处理
boolean wasSetUp = processPackageUri(packageUri);
if (!wasSetUp) {
return;
}
bindUi(R.layout.install_confirm, false);
//判断是否是未知来源的应用,如果开启允许安装未知来源选项则直接初始化安装
checkIfAllowedAndInitiateInstall();
}
private boolean processPackageUri(final Uri packageUri) {
mPackageURI = packageUri;
//得到packageUri的Scheme协议接着根据这个Scheme协议分别对package协议和file协议进行处理,如果不是这两个协议就会关闭PackageInstallerActivity并return false
final String scheme = packageUri.getScheme();
switch (scheme) {
case SCHEME_PACKAGE: {
try {
...
} break;
case SCHEME_FILE: {
File sourceFile = new File(packageUri.getPath());//创建一个新的file
//得到sourceFile的包信息 上篇文章说过了,就不再阐述了
PackageParser.Package parsed = PackageUtil.getPackageInfo(this, sourceFile);//解析apk信息
if (parsed == null) {
Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
showDialogInner(DLG_PACKAGE_ERROR);
setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
return false;
}
//对parsed进行进一步处理得到包信息PackageInfo
mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
PackageManager.GET_PERMISSIONS, 0, 0, null,
new PackageUserState());
mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
} break;
default: {
Log.w(TAG, "Unsupported scheme " + scheme);
setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
finish();
return false;
}
}
return true;
}
private void checkIfAllowedAndInitiateInstall() {
//判断如果允许安装未知来源或者根据Intent判断得出该APK不是未知来源
if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
//初始化安装
initiateInstall();
return;
}
// 如果管理员限制来自未知源的安装, 就弹出提示Dialog或者跳转到设置界面
if (isUnknownSourcesDisallowed()) {
if ((mUserManager.getUserRestrictionSource(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
Process.myUserHandle()) & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) {
showDialogInner(DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER);
return;
} else {
startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
finish();
}
} else {
handleUnknownSources();
}
}
private void initiateInstall() {
String pkgName = mPkgInfo.packageName;//得到包名
String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
if (oldName != null && oldName.length > 0 && oldName[0] != null) {
pkgName = oldName[0];
mPkgInfo.packageName = pkgName;
mPkgInfo.applicationInfo.packageName = pkgName;
}
try {
//根据包名获取应用程序信息
mAppInfo = mPm.getApplicationInfo(pkgName,
PackageManager.MATCH_UNINSTALLED_PACKAGES);//获取应用程序信息ApplicationInfo
if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
mAppInfo = null;
}
} catch (NameNotFoundException e) {
mAppInfo = null;
}
//初始化安装确认界面
startInstallConfirm()
}
private void startInstallConfirm() {
//省略初始化界面代码
...
//创建AppSecurityPermissions ,提取apk中所有的权限并展示出来
AppSecurityPermissions perms = new AppSecurityPermissions(this, mPkgInfo);
final int N = perms.getPermissionCount(AppSecurityPermissions.WHICH_ALL);
if (mAppInfo != null) {
msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
? R.string.install_confirm_question_update_system
: R.string.install_confirm_question_update;
mScrollView = new CaffeinatedScrollView(this);
mScrollView.setFillViewport(true);
boolean newPermissionsFound = false;
if (!supportsRuntimePermissions) {
newPermissionsFound =
(perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW) > 0);
if (newPermissionsFound) {
permVisible = true;
mScrollView.addView(perms.getPermissionsView(
AppSecurityPermissions.WHICH_NEW));//2
}
}
if (!permVisible) {
//
bindUi(R.layout.install_confirm, true);
mScrollView = null;
}
...
}
- 1、7.0以上根据content协议会走到installStart,其他的会走到PackageInstallerActivity
- 2、7.0以上会将content协议的url转成file协议,然后最终也走到了PackageInstallerActivity
- 3、PackageInstallerActivity会对file协议和package协议的url进行处理,如果是file协议会解析apk文件得到PackageInfo
- 4、PackageInstallerActivity会对未知来源进行处理
安装apk
上面源码分析到bindUi我们看下源码
//layout是install_confirm
private void bindUi(int layout, boolean enableOk) {
setContentView(layout);
mOk = (Button) findViewById(R.id.ok_button);
mCancel = (Button)findViewById(R.id.cancel_button);
mOk.setOnClickListener(this);
mCancel.setOnClickListener(this);
mEnableOk = enableOk;
mOk.setEnabled(enableOk);
PackageUtil.initSnippetForNewApp(this, mAppSnippet, R.id.app_snippet);
}
实际就是设置布局并且设置点击事件,我们主要看mok的点击事件
public void onClick(View v) {
if (v == mOk) {
if (mOk.isEnabled()) {
if (mOkCanInstall || mScrollView == null) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
startInstall();//1
}
} else {
mScrollView.pageScroll(View.FOCUS_DOWN);
}
}
} else if (v == mCancel) {
setResult(RESULT_CANCELED);
........
finish();
}
}
private void startInstall() {
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallInstalling.class);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (mOriginatingURI != null) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
}
..
startActivity(newIntent);
finish();
}
通过startActivity跳转到InstallInstalling
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.install_installing);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
if ("package".equals(mPackageURI.getScheme())) {
try {
getPackageManager().installExistingPackage(appInfo.packageName);
launchSuccess();
} catch (PackageManager.NameNotFoundException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
//根据mPackageURI创建一个对应的File
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
sourceFile), R.id.app_snippet);
//如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId
//mSessionId是安装包的会话id mInstallId是等待的安装事件id
if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
//向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调
try {
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
}
} else {
//创建SessionParams,它用来代表安装会话的参数,
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
params.originatingUri = getIntent()
.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
params.originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
UID_UNKNOWN);
//解析参数并复制给SessionParams
File file = new File(mPackageURI.getPath());
try {
PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
params.setAppPackageName(pkg.packageName);
params.setInstallLocation(pkg.installLocation);
params.setSize(
PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
} catch (PackageParser.PackageParserException e) {
...
}
try {
//返回一个新的mInstallId
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
try {
//创建并返回mSessionId
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} catch (IOException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
}
...
mSessionCallback = new InstallSessionCallback();
}
}
@Override
protected void onResume() {
super.onResume();
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
//根据sessionid获取SessionInfo
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
}
}
}
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
broadcastIntent.setPackage(
getPackageManager().getPermissionControllerPackageName());
broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallInstalling.this,
mInstallId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);
if (!isCancelled()) {
launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
}
}
}
public void commit(@NonNull IntentSender statusReceiver) {
try {
//mSession实际是IPackageInstallerSession,最终会调用PackageInstallerSession的commit方法
mSession.commit(statusReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Override
public void commit(IntentSender statusReceiver) {
Preconditions.checkNotNull(statusReceiver);
...
mActiveCount.incrementAndGet();
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
}
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
final PackageInfo pkgInfo = mPm.getPackageInfo(
params.appPackageName, PackageManager.GET_SIGNATURES
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
final ApplicationInfo appInfo = mPm.getApplicationInfo(
params.appPackageName, 0, userId);
synchronized (mLock) {
if (msg.obj != null) {
mRemoteObserver = (IPackageInstallObserver2) msg.obj;//获取到adapter.getBinder的值
}
try {
commitLocked(pkgInfo, appInfo)
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);//3
}
return true;
}
}
};
private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
throws PackageManagerException {
...
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
installerPackageName, installerUid, user, mCertificates);
}
mPm实际是PMS也就是说此时会到PMS的installStage方法
实际就是做了两件事情:
将apk信息封装到Session中,然后调用PackageInstaller.session的commit方法,最后交给pms进行处理
解析apk的封装
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
Certificate[][] certificates) {
...
//消息类型是INIT_COPY
final Message msg = mHandler.obtainMessage(INIT_COPY);
final int installReason = fixUpInstallReason(installerPackageName, installerUid,
sessionParams.installReason);
//安装的参数
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, certificates, installReason);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
...
//发送消息
mHandler.sendMessage(msg);
}
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
//mBound用于标识是否绑定了服务,默认值为false
if (!mBound) {
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
//如果没有绑定服务,重新绑定,connectToService方法内部如果绑定成功会将mBound置为true
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
params.traceCookie);
}
//绑定服务失败则return
return;
} else {
//绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
mPendingInstalls.add(idx, params);
}
} else {
//已经绑定服务
mPendingInstalls.add(idx, params);
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
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);
//mDefContainerConn实际是DefaultContainerConnection
if (mContext.bindServiceAsUser(service, mDefContainerConn,
Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//如果绑定DefaultContainerService成功,mBound会置为ture
mBound = true;
return true;
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return false;
}
}
class DefaultContainerConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
final IMediaContainerService imcs = IMediaContainerService.Stub
.asInterface(Binder.allowBlocking(service));
mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, Object));
}
public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
}
case MCS_BOUND: {
//msg.obj如果为null,mContainerService 为null
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
}
if (mContainerService == null) {
if (!mBound) {//false则表示没有绑定服务成功
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
params.serviceError();//5
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
params.traceMethod, params.traceCookie);
}
return;
}
//绑定失败,清空安装请求队列
mPendingInstalls.clear();
} else {
//继续等待绑定服务
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
//msg.obj!=null
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
if (params.startCopy()) {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
//如果APK安装成功,删除本次安装请求
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);
sendMessageDelayed(ubmsg, 10000);
}
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
//如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}else {
Slog.w(TAG, "Empty queue");
}
break;
}
image.png
复制apk
startCopy方法
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
//startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
if (++mRetries > MAX_RETRIES) {
//发送MCS_GIVE_UP消息
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
} else {
//复制apk
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
//安装apk,后面分析到这里注意下
handleReturnCode();
return res;
}
handleStartCopy方法
public void handleStartCopy() throws RemoteException {
...
//确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// APK不能同时安装在SD卡和Data分区
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
//安装标志冲突,Instant Apps不能安装到SD卡中
} else if (onSd && ephemeral) {
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
//获取APK的少量的信息,封装到PackageInfoLite
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);//1
if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
...
if (ret == PackageManager.INSTALL_SUCCEEDED) {
//判断安装的位置
int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
}
...
}else{
loc = installLocationPolicy(pkgLite);
...
}
}
//根据InstallParams创建InstallArgs对象
final InstallArgs args = createInstallArgs(this);
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
...
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(
verifierUser.getIdentifier(), installFlags, installerUid)) {
...
} else{
ret = args.copyApk(mContainerService, true);
}
}
mRet = ret;
}
installArgs是个抽象类,实现类有三个:FIleInstallArgs(处理data分区)、AsecInstallArgs(SD卡分区)、MoveInstallArgs(已安装APK的移动逻辑)
以FileInstallArgs为例,FileInstallArgs的copyApk
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
try {
return doCopyApk(imcs, temp);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
...
try {
final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
//创建临时文件存储目录
final File tempDir =
mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);//1
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
Slog.w(TAG, "Failed to create copy file: " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
...
int ret = PackageManager.INSTALL_SUCCEEDED;
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);//2
...
return ret;
}
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);
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 {
//拷贝apk
copyFile(pkg.baseCodePath, target, "base.apk");
if (!ArrayUtils.isEmpty(pkg.splitNames)) {
for (int i = 0; i < pkg.splitNames.length; i++) {
copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
}
}
return PackageManager.INSTALL_SUCCEEDED;
}
image.png
安装apk
void handleReturnCode() {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装前处理,检查apk的状态,确保apk是可靠的
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
installPackageTracedLI(args, res);
}
//安装后收尾
args.doPostInstall(res.returnCode, res.uid);
}
...
}
});
}
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
...
//1、创建PackageParser 解析apk
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
//解析APK
pkg = pp.parsePackage(tmpPackageFile, parseFlags);//1
} catch (PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
// 2、检查APK是否存在
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
//获取没被改名前的包名
String oldName = mSettings.getRenamedPackageLPr(pkgName)
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
pkg.setPackageName(oldName);//2
pkgName = pkg.packageName;
replace = true;//设置标志位表示是替换安装
if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
+ oldName + " pkgName=" + pkgName);
}
...
}
PackageSetting ps = mSettings.mPackages.get(pkgName);
//3、查看Settings中是否存有要安装的APK的信息,如果有就获取签名信息
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
PackageSetting signatureCheckPs = ps;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
if (libraryEntry != null) {
signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
}
}
//检查签名的正确性
if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {
if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) {
res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+ pkg.packageName + " upgrade keys do not match the "
+ "previously installed version");
return;
}
}
...
}
int N = pkg.permissions.size();
for (int i = N-1; i >= 0; i--) {
//遍历每个权限,对权限进行处理
PackageParser.Permission perm = pkg.permissions.get(i);
BasePermission bp = mSettings.mPermissions.get(perm.info.name);
}
}
}
if (systemApp) {
if (onExternal) {
//系统APP不能在SD卡上替换安装
res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Cannot install updates to system apps on sdcard");
return;
} else if (instantApp) {
//系统APP不能被Instant App替换
res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
"Cannot update a system app with an instant app");
return;
}
}
...
//4、重命名临时文件
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
return;
}
startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
//替换安装
replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res, args.installReason);
} else {
//安装新的APK
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
//更新应用程序所属的用户
res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
ps.setUpdateAvailable(false /*updateAvailable*/);
}
...
}
}
//安装最新的
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res, int installReason) {
...
try {
//扫描APK
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
//更新Settings信息
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装成功后,为新安装的应用程序准备数据
prepareAppDataAfterInstallLIF(newPackage);
} else {
//安装失败则删除APK
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
image.png