免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

      APK安裝流程:點擊下載應(yīng)用了解安裝的全過程

      一講到APK安裝流程,它有四種安裝方式:

      • 系統(tǒng)應(yīng)用和預(yù)制應(yīng)用安裝,開機時完成,沒有安裝界面,在PKMS的構(gòu)造函數(shù)中歐冠完成安裝
      • 網(wǎng)絡(luò)下載應(yīng)用安裝,通過應(yīng)用商店來完成,調(diào)用PackageManager.installPackages(),有安裝界面
      • ADB工具安裝,沒有安裝界面,它通過啟動pm腳本的形式,然后調(diào)用com.android.commands.pm.Pm類,之后調(diào)用到PMS.installStage()完成安裝
      • 第三方應(yīng)用安裝,通過SD卡里的APK文件安裝,有安裝界面,由packageinstaller.apk應(yīng)用處理安裝及卸載過程的界面.

      均是通過PackageInstallObserver來監(jiān)聽安裝是否成功。

      下面我們通過點擊下載應(yīng)用安裝來了解安裝的過程:

      先說個大概:

      1.將APK的信息通過IO流的形式寫入到PackageInstaller.Session中。2.調(diào)用PackageInstaller.Session的commit方法,將APK的信息交由PKMS處理。3.拷貝APK4.最后進行安裝

      在點擊一個未安裝的apk后,會彈出安裝界面,點擊確定按鈕后,會進入PackageInstallerActivity界面,后面會觸發(fā)bindUi方法,彈出底部安裝界面。這個主要是由bindUi構(gòu)成,上面會有取消和安裝兩個按鈕,點擊之后就會調(diào)用startInstall()進行安裝。

      //PackageInstallerActivity.javaprivate 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 { //進行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();}

      在startInstall方法組裝了一個Intent,并跳轉(zhuǎn)到InstallInstalling這個Activity,并關(guān)閉掉當前的PackageInstallerActivity。在InstallInstalling主要用于向包管理器發(fā)送包的信息并處理包管理的回調(diào)。

      2.1 PackageInstaller安裝APK

      在啟動InstallInstalling后,進入onCreate方法:

      //InstallInstallingprotected 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)閉當前的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進行進程間通信,最終調(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,然后提交。

      //InstallInstallingprotected 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(),最終進入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 { @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進行提交 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方法,進行安裝。

      在里面會看到一個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 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綁定的安裝會話,代表著一個在進行中的安裝。Session類是對IPackageInstaller.openSession(sessionId) 獲取的 PackageInstallerSession(系統(tǒng)服務(wù)端)的封裝。

      Session的創(chuàng)建和打開 具體實現(xiàn)是在 PackageInstallerService中,主要是 初始化apk的安裝信息及環(huán)境,并創(chuàng)建一個sessionId,將安裝Session與sessionId 進行綁定.

      接著我們回到InstallingAsyncTask中,在這里調(diào)用了session.commit方法:

      //PackageInstaller public void commit(@NonNull IntentSender statusReceiver) { try { //調(diào)用PackageInstallerSession的commit方法,進入到j(luò)ava框架層 mSession.commit(statusReceiver, false); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }//PackageInstallerSession.javapublic 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來進行進程間的通信,最終會調(diào)用PackageInstallerSession的commit方法。在這里發(fā)送了一個MSG_STREAM_VALIDATE_AND_COMMIT的信號,并在handler中進行處理: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 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 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.2 PMS執(zhí)行安裝

      /PackageManagerService.javavoid installStage(List 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的消息進行處理:

      //PackageManagerService.javavoid 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() { …… //解析包 返回最小的細節(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.javaint 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方法//PackagemanagerSeriveUtilsprivate 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é)束完拷貝之后,就要進入真正的安裝了,流程如下:

      //PackageManagerService.javaprivate 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ù)來進行安裝 processInstallRequestsAsync( res.returnCode == PackageManager.INSTALL_SUCCEEDED, Collections.singletonList(new InstallRequest(args, res))); } }//排隊執(zhí)行異步操作private void processInstallRequestsAsync(boolean success, List installRequests) { mHandler.post(() -> { if (success) { for (InstallRequest request : installRequests) { //進行檢驗,如果之前安裝失敗,則清除無用信息 request.args.doPreInstall(request.installResult.returnCode); } synchronized (mInstallLock) { //安裝的核心方法,進行解析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 requests) { ……. //分析當前任何狀態(tài),分析包并對其進行初始化驗證 prepareResult = preparePackageLI(request.args, request.installResult); …… //根據(jù)準備階段解析包的信息上下文,進一步解析 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主要做了以下事情:

      • 分析當前任何狀態(tài),分析包并對其進行初始化驗證
      • 根據(jù)準備階段解析包的信息上下文,進一步解析
      • 驗證掃描后包的信息好狀態(tài),確保安裝成功
      • 提交所有騷哦歐廟的包并更新系統(tǒng)狀態(tài)
      • 完成APK安裝

      在 preparePackageLI() 內(nèi)使用 PackageParser2.parsePackage() 解析AndroidManifest.xml,獲取四大組件等信息;使用ParsingPackageUtils.getSigningDetails() 解析簽名信息;重命名包最終路徑 等。

      完成了解析和校驗準備工作后,最后一步就是對apk的安裝了。這里調(diào)用了executePostCommitSteps準備app數(shù)據(jù),并執(zhí)行dex優(yōu)化。

      //PackageManagerService.javaprivate void executePostCommitSteps(CommitRequest commitRequest) { //進行安裝 prepareAppDataAfterInstallLIF(pkg); ……. final boolean performDexopt = (!instantApp || Global.getInt(mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0) && !pkg.isDebuggable() && (!onIncremental); //為新的代碼路徑準備應(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守護進程的入口:

      public class Installer extends SystemService { @Override public void onStart() { if (mIsolated) { mInstalld = null; } else { //通過Binder調(diào)用到進程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 { //進行安裝操作 return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, targetSdkVersion); } catch (Exception e) { throw InstallerException.from(e); } } }

      可以看到最終調(diào)用了Installd的createAppData方法進行安裝。Installer是Java層提供的Java API接口,Installd 則是在init進程啟動的具有root權(quán)限的Daemon進程。

      在processInstallRequestsAsync最后一步時調(diào)用了restoreAndPostInstall,在安裝完成時會發(fā)送POST_INSTALL消息:

      //PackageManagerService.javaprivate 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 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)用圖標了。

      鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
      (0)
      用戶投稿
      上一篇 2022年7月9日 15:13
      下一篇 2022年7月9日 15:13

      相關(guān)推薦

      • Riverlane聯(lián)手Rigetti:解決超導(dǎo)量子計算機關(guān)鍵糾錯步驟

        (圖片來源:網(wǎng)絡(luò)) 最近,糾錯量子計算操作系統(tǒng)公司Riverlane和量子/經(jīng)典混合計算公司Rigetti宣布合作,雙方將共同探索由英國創(chuàng)新機構(gòu)Innovate UK支持的項目——…

        2022年6月30日
      • 智慧畜牧開啟養(yǎng)殖新時代

        科協(xié)頻道、《科研成果與傳播》雜志共同推出“科技引領(lǐng) 筑夢鄉(xiāng)村”專欄,聚焦農(nóng)業(yè)科技前沿,邀請各科研團隊與青年科技工作者分享最新行業(yè)科研動態(tài)以及他們的科研故事。 當今時代,萬物互聯(lián),數(shù)…

        2022年8月7日
      • 未央今日播報:國家網(wǎng)信辦發(fā)布互聯(lián)網(wǎng)用戶賬號信息管理規(guī)定

        國家網(wǎng)信辦發(fā)布《互聯(lián)網(wǎng)用戶賬號信息管理規(guī)定》 6月27日,國家互聯(lián)網(wǎng)信息辦公室發(fā)布《互聯(lián)網(wǎng)用戶賬號信息管理規(guī)定》,自2022年8月1日起施行?!兑?guī)定》明確了,互聯(lián)網(wǎng)個人用戶注冊、使…

        2022年6月29日
      • 真的有兩個宇宙?鏡像宇宙理論,或能解決宇宙膨脹之謎

        大約138億年前,我們的宇宙還是一個奇點,今天宇宙中所有的物質(zhì)都集中在這個沒有空間的奇點內(nèi),甚至連時間都不存在。 突然,這個奇點發(fā)生了大爆炸,誕生了今天的宇宙,也創(chuàng)造了時間和空間,…

        2022年6月13日
      • 華為Nova 9跌至“新低價”,對比榮耀50,該怎么選?

        時間過得真快,為了給618沖銷量,華為和榮耀也來湊熱鬧。許多網(wǎng)友發(fā)現(xiàn),在主流電商平臺,華為Nova 9和榮耀50的入手門檻都已經(jīng)降低,到手價普遍在2000左右。雖然這兩款手機的性價…

        2022年6月22日
      • 生活中淡化斑點的方法 醫(yī)格仕祛斑淺談淡斑技巧

          臉上出現(xiàn)些些許許的斑點是非常讓人頭疼的,尤其大多都出現(xiàn)在女性臉上,這讓愛美的女性非常難受。因此很多人都會想方設(shè)法的淡化斑點或者祛斑。很多人都在尋找生活中淡化斑點的方法?醫(yī)格仕祛…

        2022年7月7日
      • 兩敗俱傷!前國足“最強歸化”遭足協(xié)放棄后:淪落踢巴乙

        中超聯(lián)賽曾經(jīng)獨造87球,幫助江蘇蘇寧勇奪聯(lián)賽冠軍的特謝拉,曾經(jīng)被視為中國男足的“最強歸化”,而他也已經(jīng)完全符合中國男足的歸化條件,進入了里皮的歸化候選范圍。根據(jù)此前記者白國華透露的…

        2022年7月18日
      • 000004st國華

        車聯(lián)網(wǎng)關(guān)聯(lián)理由 子公司愛加密重磅推出車聯(lián)網(wǎng)整體安全解決方案,側(cè)重端點及數(shù)據(jù)傳輸防護,主要防護對象為車聯(lián)網(wǎng)用戶端移動 App (包括安卓、 iOS 、 SO 庫、 SDK 、H5等應(yīng)…

        2022年6月14日
      • 新買的iphone四碼不合一意味著什么?大概率是翻新機了

        很多網(wǎng)友都知道,正版原裝的iphone一定是四碼合一的,那么如果買到了四碼不合一的iphonne,意味著什么呢? 首先,大家收到新買的iphone的時候,一定要在拆封之前先檢查序列…

        2022年6月28日
      • 借唄明明有額度為什么借不出來 以下4點原因要知道!

        在如今,很多人使用借唄的時候,借唄明明有額度,但借錢的時候卻無法借出來,這其實是因為各種原因?qū)е碌模敲唇鑶h明明有額度為什么借不出來?下文就來帶大家了解一下。 1、被限制使用:之前…

        2022年9月2日

      聯(lián)系我們

      聯(lián)系郵箱:admin#wlmqw.com
      工作時間:周一至周五,10:30-18:30,節(jié)假日休息