?Android系統(tǒng)啟動篇
1,《android系統(tǒng)啟動流程簡介》
2,《android init進(jìn)程啟動流程》
3,《android zygote進(jìn)程啟動流程》
4,《Android SystemServer進(jìn)程啟動流程》
5,《android launcher啟動流程》
6,《Android Activity啟動過程詳解》
Android系統(tǒng)開發(fā)準(zhǔn)備篇
1,《Android 源碼下載和編譯》
2,《android 11源碼編譯和pixel3 刷機(jī)》
3,《Android Framework代碼IDE加載和調(diào)試》
Android系統(tǒng)開發(fā)實踐篇
1,《android設(shè)置默認(rèn)輸入法》
2,《android framework預(yù)制APK應(yīng)用》
3,《Android系統(tǒng)層面限制應(yīng)用開機(jī)自啟動詳解》
4,《android單獨編譯framework模塊并push》
5,《Android Framework開發(fā)系統(tǒng)問題分析》
Android系統(tǒng)開發(fā)核心知識儲備篇
1,《Android編譯系統(tǒng)-envsetup和lunch代碼篇》
2,《Android編譯系統(tǒng)-概念篇》
3,《android日志系統(tǒng)詳解》
4,《Android系統(tǒng)Handler詳解》
5,《Android系統(tǒng)Binder詳解》
6,《Android中Activity、View和Window關(guān)系詳解》
7,《android view繪制流程詳解》
8,《Android讀取系統(tǒng)屬性詳解》
9,《android 窗口管理機(jī)制詳解》
10,《初識Android系統(tǒng)》
11,《android中AMS進(jìn)程通知Zygote進(jìn)程fork新進(jìn)程的通信方式》
Android核心功能詳解篇
1,《android應(yīng)用市場點擊下載APK安裝詳解》
2,《Android 手勢導(dǎo)航(從下往上滑動進(jìn)入多任務(wù)頁面)》
3,《android手勢分析(應(yīng)用界面左往右邊滑動退出應(yīng)用)》
4,《android應(yīng)用安裝流程詳解》
5,《android11安裝應(yīng)用觸發(fā)桌面圖標(biāo)刷新流程》
6,《Android系統(tǒng)多任務(wù)Recents詳解》
7,《android系統(tǒng)導(dǎo)航欄視圖分析》
———————————————————————————————————————————
目錄
一,背景介紹
二,安裝過程
2.1 流程概述
2.2 PackageInstaller安裝APK
2.3 PMS執(zhí)行安裝
一,背景介紹
android的APK安裝流程,有四種安裝方式:
1,系統(tǒng)應(yīng)用和預(yù)制應(yīng)用安裝,開機(jī)時完成,沒有安裝界面,在PKMS的構(gòu)造函數(shù)中歐冠完成安裝
2,網(wǎng)絡(luò)下載應(yīng)用安裝,通過應(yīng)用商店來完成,調(diào)用PackageManager.installPackages(),有安裝界面
3,ADB工具安裝,沒有安裝界面,它通過啟動pm腳本的形式,然后調(diào)用com.android.commands.pm.Pm類,之后調(diào)用到PMS.installStage()完成安裝
4,第三方應(yīng)用安裝,通過SD卡里的APK文件安裝,有安裝界面,由packageinstaller.apk應(yīng)用處理安裝及卸載過程的界面.
均是通過PackageInstallObserver來監(jiān)聽安裝是否成功。
二,安裝過程
2.1 流程概述
應(yīng)用安裝主要流程:
1,將APK的信息通過IO流的形式寫入到PackageInstaller.Session中。
2,調(diào)用PackageInstaller.Session的commit方法,將APK的信息交由PKMS處理。
3,拷貝APK
4,最后進(jìn)行安裝
????????在應(yīng)用市場點擊一個未安裝的apk后,發(fā)送廣播打開PackageInstallerActivity,拉起com.android.packageinstaller(斷點的進(jìn)程)應(yīng)用,彈出安裝界面,這個主要是由bindUi構(gòu)成,點擊之后就會調(diào)用startInstall()進(jìn)行安裝。
/PackageInstallerActivity.java
private void bindUi() {
mAlert.setIcon(mAppSnippet.icon);
mAlert.setTitle(mAppSnippet.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
//進(jìn)行APK安裝
startInstall();
}
}
}, null);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
// Cancel and finish
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
//如果mSessionId存在,執(zhí)行setPermissionsResult()完成取消安裝
mInstaller.setPermissionsResult(mSessionId, false);
}
finish();
}, null);
setupAlert();
......
}
//點擊”安裝“,跳轉(zhuǎn) InstallInstalling - 開始安裝
private void startInstall() {
// Start subactivity to actually install the application
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 (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(newIntent);
finish();
}
其中,R.layout.install_content_view布局視圖如下:
????????在startInstall方法組裝了一個Intent,并跳轉(zhuǎn)到InstallInstalling這個Activity,并關(guān)閉掉當(dāng)前的PackageInstallerActivity。在InstallInstalling主要用于向包管理器發(fā)送包的信息并處理包管理的回調(diào)。
2.2 PackageInstaller安裝APK
在啟動InstallInstalling后,進(jìn)入onCreate方法:
//InstallInstalling
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
......
setupAlert();
requireViewById(R.id.installing).setVisibility(View.VISIBLE);
if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
try {
//.根據(jù)mInstallId向InstallEventReceiver注冊一個觀察者,launchFinishBasedOnResult會接收到安裝事件的回調(diào),無論安裝成功或者失敗都會關(guān)閉當(dāng)前的Activity(InstallInstalling)。如果savedInstanceState為null,代碼的邏輯也是類似的
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
// Does not happen
}
} else {
......
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) {
Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
Log.e(LOG_TAG,
"Cannot calculate installed size " + file + ". Try only apk size.");
params.setSize(file.length());
} catch (IOException e) {
Log.e(LOG_TAG,
"Cannot calculate installed size " + file + ". Try only apk size.");
params.setSize(file.length());
}
try {
//向InstallEventReceiver注冊一個觀察者返回一個新的mInstallId,
//其中InstallEventReceiver繼承自BroadcastReceiver,用于接收安裝事件并回調(diào)給EventResultPersister。
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
try {
//PackageInstaller的createSession方法內(nèi)部會通過IPackageInstaller與PackageInstallerService進(jìn)行進(jìn)程間通信,最終調(diào)用的是PackageInstallerService的createSession方法來創(chuàng)建并返回mSessionId
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} catch (IOException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
}
mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
mSessionCallback = new InstallSessionCallback();
}
}
????????在onCreate中通過PackageInstaller通過創(chuàng)建Session并返回mSesionId,接著會在onResume中,會開啟InstallingAsynTask,把包信息寫入mSessionId對應(yīng)的session,然后提交。
//InstallInstalling
protected void onResume() {
super.onResume();
// This is the first onResume in a single life of the activity
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
//獲取sessionInfo
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
//創(chuàng)建內(nèi)部類InstallingAsyncTask的對象,調(diào)用execute(),最終進(jìn)入onPostExecute()
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {
// we will receive a broadcast when the install is finished
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
}
}
}
private final class InstallingAsyncTask extends AsyncTask<Void, Void,
PackageInstaller.Session> {
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session;
try {
session = getPackageManager().getPackageInstaller().openSession(mSessionId);
} catch (IOException e) {
return null;
}
session.setStagingProgress(0);
try {
File file = new File(mPackageURI.getPath());
try (InputStream in = new FileInputStream(file)) {
long sizeBytes = file.length();
//從session中獲取輸出流
try (OutputStream out = session
.openWrite("PackageInstaller", 0, sizeBytes)) {
byte[] buffer = new byte[1024 * 1024];
......
}
}
return session;
} catch (IOException | SecurityException e) {
......
}
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntent.setPackage(getPackageName());
broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallInstalling.this,
mInstallId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
//包寫入session進(jìn)行提交
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);
if (!isCancelled()) {
launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
}
}
}
}
????????在InstallingAsyncTask的doInBackground()里會根據(jù)包的Uri,將APK的信息通過IO流的形式寫入到PackageInstaller.Session中,最后會在onPostExecute()中調(diào)用PackageInstaller.Session的commit方法,進(jìn)行安裝。
????????在里面會看到一個PackageInstaller,也就是APK安裝器,其實在ApplicationPackageManager的getPackageInstaller中創(chuàng)建的:
//ApplicationPackageManager
@Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
if (mInstaller == null) {
try {
mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
mContext.getPackageName(), getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return mInstaller;
}
}
????????在這里會傳入mPM.getPackageInstaller(),也就是IpacageInstaller的實例,其具體實現(xiàn)也就是PackageInstallerService, 其通過IPC的方式。它在初始化的時候會讀取/data/system目錄下的install_sessions文件,這個文件保存了系統(tǒng)未完成的Install Session。PMS則會根據(jù)文件的內(nèi)容創(chuàng)建PackageInstallerSession對象并從插入到mSessions中。
//PackageInstallerService.java
public PackageInstallerService(Context context, PackageManagerService pm,
Supplier<PackageParser2> apexParserSupplier) {
mContext = context;
mPm = pm;
mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
mInstallHandler = new Handler(mInstallThread.getLooper());
mCallbacks = new Callbacks(mInstallThread.getLooper());
mSessionsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
"package-session");
//這個文件保存了系統(tǒng)未完成的`Install Session`
mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
mSessionsDir.mkdirs();
mApexManager = ApexManager.getInstance();
mStagingManager = new StagingManager(this, context, apexParserSupplier);
}
????????再來看下Session,是在于mSeesionId綁定的安裝會話,代表著一個在進(jìn)行中的安裝。Session類是對IPackageInstaller.openSession(sessionId) 獲取的 PackageInstallerSession(系統(tǒng)服務(wù)端)的封裝。
????????Session的創(chuàng)建和打開 具體實現(xiàn)是在 PackageInstallerService中,主要是 初始化apk的安裝信息及環(huán)境,并創(chuàng)建一個sessionId,將安裝Session與sessionId 進(jìn)行綁定.
????????接著我們回到InstallingAsyncTask中,在這里調(diào)用了session.commit方法:
//PackageInstaller
public void commit(@NonNull IntentSender statusReceiver) {
try {
//調(diào)用PackageInstallerSession的commit方法,進(jìn)入到j(luò)ava框架層
mSession.commit(statusReceiver, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
//PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
......
//如果尚未調(diào)用,則會話將被密封。此方法可能會被多次調(diào)用以更新狀態(tài)接收者驗證調(diào)用者權(quán)限
if (!markAsSealed(statusReceiver, forTransfer)) {
return;
}
//不同的包
if (isMultiPackage()) {
final SparseIntArray remainingSessions = mChildSessionIds.clone();
final IntentSender childIntentSender =
new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
.getIntentSender();
boolean sealFailed = false;
for (int i = mChildSessionIds.size() - 1; i >= 0; --i) {
final int childSessionId = mChildSessionIds.keyAt(i);
// seal all children, regardless if any of them fail; we'll throw/return
// as appropriate once all children have been processed
if (!mSessionProvider.getSession(childSessionId)
.markAsSealed(childIntentSender, forTransfer)) {
sealFailed = true;
}
}
if (sealFailed) {
return;
}
}
dispatchStreamValidateAndCommit();
}
private void dispatchStreamValidateAndCommit() {
mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
}
mSession的類型為IPackageInstallerSession,這說明要通過IPackageInstallerSession來進(jìn)行進(jìn)程間的通信,最終會調(diào)用PackageInstallerSession的commit方法。 在這里發(fā)送了一個MSG_STREAM_VALIDATE_AND_COMMIT的信號,并在handler中進(jìn)行處理:
public boolean handleMessage(Message msg) {
case MSG_STREAM_VALIDATE_AND_COMMIT:
handleStreamValidateAndCommit();
break;
case MSG_INSTALL:
handleInstall(); //
break;
......
}
private void handleStreamValidateAndCommit() {
......
if (unrecoverableFailure != null) {
onSessionVerificationFailure(unrecoverableFailure);
// fail other child sessions that did not already fail
for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
PackageInstallerSession session = nonFailingSessions.get(i);
session.onSessionVerificationFailure(unrecoverableFailure);
}
}
}
if (!allSessionsReady) {
return;
}
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}
在handleStreamValidateAndCommit又發(fā)送了消息MSG_INSTALL,實際上真正在執(zhí)行的是在handleInstall中:
private void handleInstall() {
......
// 對于 multiPackage 會話,請在鎖之外讀取子會話,因為在持有鎖的情況下讀取子會話可能會導(dǎo)致死鎖 (b123391593)。
List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
try {
synchronized (mLock) {
installNonStagedLocked(childSessions);
}
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);
}
}
private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
throws PackageManagerException {
......
if (!success) {
sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
failure.error, failure.getLocalizedMessage(), null);
return;
}
mPm.installStage(installingChildSessions);
} else {
mPm.installStage(installingSession);
}
}
????????最后執(zhí)行到了PMS的installStage方法。在上述的過程中,通過PackageInstaller維持了Session,把安裝包寫入到Session,真正的安裝過程就要來看PMS了。
2.3 PMS執(zhí)行安裝
//PackageManagerService.java
void installStage(List<ActiveInstallSession> children)
throws PackageManagerException {
//創(chuàng)建了類型未INIT_COPY的消息
final Message msg = mHandler.obtainMessage(INIT_COPY);
//創(chuàng)建InstallParams,它對應(yīng)于包的安裝數(shù)據(jù)
final MultiPackageInstallParams params =
new MultiPackageInstallParams(UserHandle.ALL, children);
params.setTraceMethod("installStageMultiPackage")
.setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
//將InstallParams通過消息發(fā)送出去
mHandler.sendMessage(msg);
}
handler對INIT_COPY的消息進(jìn)行處理:
//PackageManagerService.java
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
//執(zhí)行APK拷貝動作
params.startCopy();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
break;
}
......
}
final void startCopy() {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
handleStartCopy();
handleReturnCode();
}
????????在這里調(diào)用了兩個方法handleStartCopy和handleReturnCode,其實現(xiàn)是在InstallParams 中。
在handleStartCopy,做了以下操作:
- 檢查空間大小,如果空間不夠則釋放無用空間
- 覆蓋原有安裝位置的文件,并根據(jù)返回結(jié)果來確定函數(shù)的返回值,并設(shè)置installFlags
- 確定是否有任何已安裝的包驗證器,如有,則延遲檢測。主要分三步:首先新建一個驗證Intent,然后設(shè)置相關(guān)的信息,之后獲取驗證器列表,最后向每個驗證器發(fā)送驗證Intent
public void handleStartCopy() {
......
//解析包 返回最小的細(xì)節(jié):pkgName、versionCode、安裝所需空間大小、獲取安裝位置等
pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
origin.resolvedPath, installFlags, packageAbiOverride);
......
//覆蓋原有安裝位置的文件,并根據(jù)返回結(jié)果來確定函數(shù)的返回值,并設(shè)置installFlags。
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 if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
ret = PackageManager.INSTALL_FAILED_INVALID_APK;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
ret = PackageManager.INSTALL_FAILED_INVALID_URI;
} else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
} else {
.......
}
}
//安裝參數(shù)
final InstallArgs args = createInstallArgs(this);
mVerificationCompleted = true;
mIntegrityVerificationCompleted = true;
mEnableRollbackCompleted = true;
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
final int verificationId = mPendingVerificationToken++;
// apk完整性校驗
if (!origin.existing) {
PackageVerificationState verificationState =
new PackageVerificationState(this);
mPendingVerification.append(verificationId, verificationState);
sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
ret = sendPackageVerificationRequest(
verificationId, pkgLite, verificationState);
......
}
}
然后來看下handleReturnCode方法:
@Override
void handleReturnCode() {
......
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
//執(zhí)行APKcopy拷貝
mRet = mArgs.copyApk();
}
//執(zhí)行安裝
processPendingInstall(mArgs, mRet);
}
}
APK的copy過程是如何拷貝的:
//packageManagerService.java
int copyApk() {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
try {
return doCopyApk();
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private int doCopyApk() {
......
int ret = PackageManagerServiceUtils.copyPackage(
origin.file.getAbsolutePath(), codeFile);
......
return ret;
}
//繼續(xù)追蹤下去,他會到PackagemanagerSeriveUtils的copyFile方法
//PackagemanagerSeriveUtils
private static void copyFile(String sourcePath, File targetDir, String targetName)
throws ErrnoException, IOException {
if (!FileUtils.isValidExtFilename(targetName)) {
throw new IllegalArgumentException("Invalid filename: " + targetName);
}
Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
final File targetFile = new File(targetDir, targetName);
final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(targetFile.getAbsolutePath(), 0644);
FileInputStream source = null;
try {
source = new FileInputStream(sourcePath);
FileUtils.copy(source.getFD(), targetFd);
} finally {
IoUtils.closeQuietly(source);
}
}
????????在這里就通過文件流的操作,把Apk拷貝到/data/app的目錄下了。結(jié)束完拷貝之后,就要進(jìn)入真正的安裝了,流程如下:
/PackageManagerService.java
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
if (args.mMultiPackageInstallParams != null) {
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
//安裝結(jié)果
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
//創(chuàng)建一個新線程來處理安轉(zhuǎn)參數(shù)來進(jìn)行安裝
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
//排隊執(zhí)行異步操作
private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
mHandler.post(() -> {
if (success) {
for (InstallRequest request : installRequests) {
//進(jìn)行檢驗,如果之前安裝失敗,則清除無用信息
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
//安裝的核心方法,進(jìn)行解析apk安裝
installPackagesTracedLI(installRequests);
}
for (InstallRequest request : installRequests) {
//再次檢驗清除無用信息
request.args.doPostInstall(
request.installResult.returnCode, request.installResult.uid);
}
}
for (InstallRequest request : installRequests) {
//備份、可能的回滾、發(fā)送安裝完成先關(guān)廣播
restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
new PostInstallData(request.args, request.installResult, null));
}
});
}
看到了核心方法installPackagesTracedLI,接著內(nèi)部執(zhí)行到了installPackagesLI方法:
//PackageMmanagerSerice.java
private void installPackagesLI(List<InstallRequest> requests) {
.......
//分析當(dāng)前任何狀態(tài),分析包并對其進(jìn)行初始化驗證
prepareResult =
preparePackageLI(request.args, request.installResult);
......
//根據(jù)準(zhǔn)備階段解析包的信息上下文,進(jìn)一步解析
final ScanResult result = scanPackageTracedLI(
prepareResult.packageToScan, prepareResult.parseFlags,
prepareResult.scanFlags, System.currentTimeMillis(),
request.args.user, request.args.abiOverride);
.......
//驗證掃描后包的信息好狀態(tài),確保安裝成功
reconciledPackages = reconcilePackagesLocked(
reconcileRequest, mSettings.mKeySetManagerService);
//提交所有的包并更新系統(tǒng)狀態(tài)。這是安裝流中唯一可以修改系統(tǒng)狀態(tài)的地方,必須在此階段之前確定所有可預(yù)測的錯誤
commitRequest = new CommitRequest(reconciledPackages,
mUserManager.getUserIds());
commitPackagesLocked(commitRequest);
.......
//完成APK安裝
executePostCommitSteps(commitRequest);
}
由上面代碼可知,installPackagesLI主要做了以下事情:
- 分析當(dāng)前任何狀態(tài),分析包并對其進(jìn)行初始化驗證
- 根據(jù)準(zhǔn)備階段解析包的信息上下文,進(jìn)一步解析
- 驗證掃描后包的信息好狀態(tài),確保安裝成功
- 提交所有騷哦歐廟的包并更新系統(tǒng)狀態(tài)
- 完成APK安裝
在 preparePackageLI() 內(nèi)使用 PackageParser2.parsePackage() 解析AndroidManifest.xml,獲取四大組件等信息;使用ParsingPackageUtils.getSigningDetails() 解析簽名信息;重命名包最終路徑 等。
完成了解析和校驗準(zhǔn)備工作后,最后一步就是對apk的安裝了。這里調(diào)用了executePostCommitSteps準(zhǔn)備app數(shù)據(jù),并執(zhí)行dex優(yōu)化。
//PackageManagerService.java
private void executePostCommitSteps(CommitRequest commitRequest) {
//進(jìn)行安裝
prepareAppDataAfterInstallLIF(pkg);
.......
final boolean performDexopt =
(!instantApp || Global.getInt(mContext.getContentResolver(),
Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& !pkg.isDebuggable()
&& (!onIncremental);
//為新的代碼路徑準(zhǔn)備應(yīng)用程序配置文件
mArtManagerService.prepareAppProfiles(
pkg,
resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
if (performDexopt) {
......
//其中分配了 dexopt 所需的庫文件
PackageSetting realPkgSetting = result.existingSettingCopied
? result.request.pkgSetting : result.pkgSetting;
if (realPkgSetting == null) {
realPkgSetting = reconciledPkg.pkgSetting;
}
//執(zhí)行dex優(yōu)化
mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
在prepareAppDataAfterInstallLIF方法中,經(jīng)過一系列的調(diào)用,最中會調(diào)用到 mInstaller.createAppData,這里也是調(diào)用Installd守護(hù)進(jìn)程的入口:
public class Installer extends SystemService {
@Override
public void onStart() {
if (mIsolated) {
mInstalld = null;
} else {
//通過Binder調(diào)用到進(jìn)程installd
connect();
}
}
private void connect() {
IBinder binder = ServiceManager.getService("installd");
......
if (binder != null) {
mInstalld = IInstalld.Stub.asInterface(binder);
try {
invalidateMounts();
} catch (InstallerException ignored) {
}
} else {
Slog.w(TAG, "installd not found; trying again");
BackgroundThread.getHandler().postDelayed(() -> {
connect();
}, DateUtils.SECOND_IN_MILLIS);
}
}
public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
String seInfo, int targetSdkVersion) throws InstallerException {
if (!checkBeforeRemote()) return -1;
try {
//進(jìn)行安裝操作
return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
targetSdkVersion);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
}
可以看到最終調(diào)用了Installd的createAppData方法進(jìn)行安裝。Installer是Java層提供的Java API接口,Installd 則是在init進(jìn)程啟動的具有root權(quán)限的Daemon進(jìn)程。
在processInstallRequestsAsync最后一步時調(diào)用了restoreAndPostInstall,在安裝完成時會發(fā)送POST_INSTALL消息:文章來源:http://www.zghlxwxcb.cn/news/detail-564227.html
//PackageManagerService.java
private void restoreAndPostInstall(
int userId, PackageInstalledInfo res, @Nullable PostInstallData data) {
.......
if (!doRestore) {
if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}
void doHandleMessage(Message msg) {
.......
case POST_INSTALL: {
.......
//處理安裝結(jié)果
handlePackagePostInstall(parentRes, grantPermissions,
killApp, virtualPreload, grantedPermissions,
whitelistedRestrictedPermissions, autoRevokePermissionsMode,
didRestore, args.installSource.installerPackageName, args.observer,
args.mDataLoaderType);
}
}
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
boolean killApp, boolean virtualPreload,
String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
int autoRevokePermissionsMode,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver, int dataLoaderType) {
......
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
updateUserIds, instantUserIds, newBroadcastWhitelist);
}
最后發(fā)送了ACTION_PACKAGE_ADDED廣播,launcher接收到這個廣播之后就會在桌面上添加應(yīng)用圖標(biāo)了。文章來源地址http://www.zghlxwxcb.cn/news/detail-564227.html
到了這里,關(guān)于android應(yīng)用市場點擊下載APK安裝詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!