??Android 源碼解讀-安裝包的安裝過程 ??

      網(wǎng)友投稿 996 2022-05-29

      App安裝過程

      源碼:Android SDK 30

      當(dāng)我們點(diǎn)擊某一個(gè) App 安裝包進(jìn)行安裝時(shí),首先會(huì)彈出一個(gè)系統(tǒng)界面指示我們進(jìn)行安裝操作。這個(gè)界面是 Android Framework 中預(yù)置的一個(gè) Activity—PackageInstallerActivity.java。

      PackageInstallerActivity

      frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

      /** */ public class PackageInstallerActivity extends AlertActivity { ... }

      看到 Activity 當(dāng)然是先從 onCreate() 開始了

      onCreat()

      public class PackageInstallerActivity extends AlertActivity { @Override protected void onCreate(Bundle icicle) { getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); super.onCreate(null); if (icicle != null) { mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY); } //mPm = PackageManagerService mPm = getPackageManager(); //mIpm = IPackageManager //將原始接口返回給包管理器。 mIpm = AppGlobals.getPackageManager(); //AppOpsManager 涵蓋了從幫助運(yùn)行時(shí)權(quán)限訪問控制和跟蹤到電池消耗跟蹤的各種功能。 mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); //提供在設(shè)備上安裝、升級(jí)和刪除應(yīng)用程序的能力。 mInstaller = mPm.getPackageInstaller(); //在多用戶系統(tǒng)上管理用戶和用戶詳細(xì)信息 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); final Intent intent = getIntent(); ... //安裝包Uri final Uri packageUri; if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) { //獲取android.content.pm.extra.SESSION_ID final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1); //獲取安裝Session的詳細(xì)信息 final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId); if (info == null || !info.sealed || info.resolvedBaseCodePath == null) { //獲取SessionInfo失敗退出安裝 finish(); return; } mSessionId = sessionId; packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath)); mOriginatingURI = null; mReferrerURI = null; } else { mSessionId = -1; packageUri = intent.getData(); mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI); mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER); } if (packageUri == null) { //獲取packageUri失敗退出安裝 setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI); finish(); return; } //解析 Uri 并為此包設(shè)置安裝程序。 boolean wasSetUp = processPackageUri(packageUri); if (!wasSetUp) { return; } } }

      在 onCreate() 方法中,首先執(zhí)行一些初始化操作,獲取PackageManager和PackageInstaller、UserManager等對(duì)象,根據(jù)當(dāng)前Intent的信息最一些邏輯判斷并彈出消息彈窗,然后獲取一些安裝包信息。接下來咱們安裝 Activity 的生命周期往下看 onStart() 沒有重寫,咱繼續(xù)往下看

      onResume()

      @Override protected void onResume() { super.onResume(); //processPackageUri已拿到mAppSnippet if (mAppSnippet != null) { // 在禁用確定按鈕的情況下加載虛擬布局,直到我們覆蓋此布局 // 開始安裝確認(rèn) bindUi(); // 檢查是否允許安裝包,如果允許則啟動(dòng)安裝。 //如果不允許顯示適當(dāng)?shù)膶?duì)話框。 checkIfAllowedAndInitiateInstall(); } if (mOk != null) { mOk.setEnabled(mEnableOk); } }

      bindUi()

      private void bindUi() { ... mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install), (ignored, ignored2) -> { if (mOk.isEnabled()) { ... startInstall(); ... } }, null); ... }

      這里點(diǎn)擊安裝按鈕進(jìn)去 startInstall() 方法,失敗的情況咱就不看了,繼續(xù)往下走著。

      startInstall()

      private void startInstall() { // 啟動(dòng)子Activity,安裝應(yīng)用程序 Intent newIntent = new Intent(); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo); newIntent.setData(mPackageURI); newIntent.setClass(this, InstallInstalling.class); ... newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); startActivity(newIntent); finish(); }

      startInstall 調(diào)用即使啟用了一個(gè)新的Activity–>InstallInstalling。會(huì)把安裝包的信息通過 Intent 傳遞到 InstallInstalling 這個(gè) Activity。

      InstallInstalling

      frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

      /** * Send package to the package manager and handle results from package manager. Once the * installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}. *

      This has two phases: First send the data to the package manager, then wait until the package * manager processed the result.

      */ public class InstallInstalling extends AlertActivity { ... }

      在這個(gè)頁面點(diǎn)擊安裝時(shí),InstallInstalling 的作用主要是向 PMS 發(fā)送包信息以及處理回調(diào)。 這有兩個(gè)階段:

      首先將數(shù)據(jù)發(fā)送給 PackageManager ;

      等待 PackageManager 處理結(jié)果(InstallSuccess 或 InstallFailed)。

      App安裝過程

      源碼:Android SDK 30

      當(dāng)我們點(diǎn)擊某一個(gè) App 安裝包進(jìn)行安裝時(shí),首先會(huì)彈出一個(gè)系統(tǒng)界面指示我們進(jìn)行安裝操作。這個(gè)界面是 Android Framework 中預(yù)置的一個(gè) Activity—PackageInstallerActivity.java。

      PackageInstallerActivity

      frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

      /** */ public class PackageInstallerActivity extends AlertActivity { ... }

      看到 Activity 當(dāng)然是先從 onCreate() 開始了

      onCreat()

      public class PackageInstallerActivity extends AlertActivity { @Override protected void onCreate(Bundle icicle) { getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); super.onCreate(null); if (icicle != null) { mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY); } //mPm = PackageManagerService mPm = getPackageManager(); //mIpm = IPackageManager //將原始接口返回給包管理器。 mIpm = AppGlobals.getPackageManager(); //AppOpsManager 涵蓋了從幫助運(yùn)行時(shí)權(quán)限訪問控制和跟蹤到電池消耗跟蹤的各種功能。 mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); //提供在設(shè)備上安裝、升級(jí)和刪除應(yīng)用程序的能力。 mInstaller = mPm.getPackageInstaller(); //在多用戶系統(tǒng)上管理用戶和用戶詳細(xì)信息 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); final Intent intent = getIntent(); ... //安裝包Uri final Uri packageUri; if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) { //獲取android.content.pm.extra.SESSION_ID final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1); //獲取安裝Session的詳細(xì)信息 final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId); if (info == null || !info.sealed || info.resolvedBaseCodePath == null) { //獲取SessionInfo失敗退出安裝 finish(); return; } mSessionId = sessionId; packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath)); mOriginatingURI = null; mReferrerURI = null; } else { mSessionId = -1; packageUri = intent.getData(); mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI); mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER); } if (packageUri == null) { //獲取packageUri失敗退出安裝 setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI); finish(); return; } //解析 Uri 并為此包設(shè)置安裝程序。 boolean wasSetUp = processPackageUri(packageUri); if (!wasSetUp) { return; } } }

      在 onCreate() 方法中,首先執(zhí)行一些初始化操作,獲取PackageManager和PackageInstaller、UserManager等對(duì)象,根據(jù)當(dāng)前Intent的信息最一些邏輯判斷并彈出消息彈窗,然后獲取一些安裝包信息。接下來咱們安裝 Activity 的生命周期往下看 onStart() 沒有重寫,咱繼續(xù)往下看

      onResume()

      @Override protected void onResume() { super.onResume(); //processPackageUri已拿到mAppSnippet if (mAppSnippet != null) { // 在禁用確定按鈕的情況下加載虛擬布局,直到我們覆蓋此布局 // 開始安裝確認(rèn) bindUi(); // 檢查是否允許安裝包,如果允許則啟動(dòng)安裝。 //如果不允許顯示適當(dāng)?shù)膶?duì)話框。 checkIfAllowedAndInitiateInstall(); } if (mOk != null) { mOk.setEnabled(mEnableOk); } }

      bindUi()

      private void bindUi() { ... mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install), (ignored, ignored2) -> { if (mOk.isEnabled()) { ... startInstall(); ... } }, null); ... }

      這里點(diǎn)擊安裝按鈕進(jìn)去 startInstall() 方法,失敗的情況咱就不看了,繼續(xù)往下走著。

      startInstall()

      private void startInstall() { // 啟動(dòng)子Activity,安裝應(yīng)用程序 Intent newIntent = new Intent(); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo); newIntent.setData(mPackageURI); newIntent.setClass(this, InstallInstalling.class); ... newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); startActivity(newIntent); finish(); }

      startInstall 調(diào)用即使啟用了一個(gè)新的Activity–>InstallInstalling。會(huì)把安裝包的信息通過 Intent 傳遞到 InstallInstalling 這個(gè) Activity。

      InstallInstalling

      frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

      /** * Send package to the package manager and handle results from package manager. Once the * installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}. *

      This has two phases: First send the data to the package manager, then wait until the package * manager processed the result.

      */ public class InstallInstalling extends AlertActivity { ... }

      在這個(gè)頁面點(diǎn)擊安裝時(shí),InstallInstalling 的作用主要是向 PMS 發(fā)送包信息以及處理回調(diào)。 這有兩個(gè)階段:

      首先將數(shù)據(jù)發(fā)送給 PackageManager ;

      等待 PackageManager 處理結(jié)果(InstallSuccess 或 InstallFailed)。

      看到 Activity 當(dāng)然是先從 onCreate() 開始了

      onCreat()

      @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ApplicationInfo appInfo = getIntent() .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); //要安裝的包的 URI mPackageURI = getIntent().getData(); if ("package".equals(mPackageURI.getScheme())) { try { //注釋1:安裝現(xiàn)有包 getPackageManager().installExistingPackage(appInfo.packageName); //安裝成功頁面 launchSuccess(); } catch (PackageManager.NameNotFoundException e) { //安裝失敗頁面 launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); } } else { //注釋2:沒有現(xiàn)有包 //根據(jù) mPackageURI 創(chuàng)建一個(gè)對(duì)應(yīng)的 File final File sourceFile = new File(mPackageURI.getPath()); //顯示應(yīng)用信息 icon,應(yīng)用名 PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile); mAlert.setIcon(as.icon); ... if (savedInstanceState != null) { //咱們第一次僅savedInstanceState==null //安裝包的會(huì)話 ID mSessionId = savedInstanceState.getInt(SESSION_ID); //我們等待的安裝事件的 ID mInstallId = savedInstanceState.getInt(INSTALL_ID); //重新登記結(jié)果;如果結(jié)果是在 Activtiy 被銷毀時(shí)交付的,則可能會(huì)立即回調(diào) try { //添加一個(gè)觀察者。如果此id已存在事件,請(qǐng)?jiān)诖苏{(diào)用內(nèi)回調(diào)。 // 向 InstallEventReceiver 注冊(cè)一個(gè)觀察者 // InstallEventReceiver 是一個(gè) BroadcastReceiver,可以通過 EventResultPersister 接收到所有的安裝事件 // 這里事件會(huì)回調(diào)給 this::launchFinishBasedOnResult InstallEventReceiver.addObserver(this, mInstallId, this::launchFinishBasedOnResult); } catch (EventResultPersister.OutOfIdsException e) { // Does not happen } } else { //咱們第一次僅savedInstanceState==null //創(chuàng)建 SessionParams,它用來攜帶會(huì)話的參數(shù) PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.setInstallAsInstantApp(false); ... params.setInstallReason(PackageManager.INSTALL_REASON_USER); File file = new File(mPackageURI.getPath()); try { // 對(duì) APK 進(jìn)行輕量級(jí)的解析,并將解析的結(jié)果賦值給 SessionParams 相關(guān)字段 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) { ... } catch (IOException e) { ... } try { // 向 InstallEventReceiver 注冊(cè)一個(gè)觀察者返回一個(gè)新的 mInstallId // InstallEventReceiver 是一個(gè) BroadcastReceiver,可以通過 EventResultPersister 接收到所有的安裝事件 // 這里事件會(huì)回調(diào)給 this::launchFinishBasedOnResult 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)部會(huì)通過 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); //監(jiān)聽會(huì)話的更改并更新進(jìn)度條 mSessionCallback = new InstallSessionCallback(); } }

      NameNotFoundException:當(dāng)找不到給定的包、應(yīng)用程序或組件名稱時(shí),將引發(fā)此異常。

      在 onCreate() 方法中,首先執(zhí)行一些初始化操作,比如獲取 mInstallId、mSessionId以及監(jiān)聽回調(diào) mSessionCallback 。接下來看看 onStart() 。

      onStart()

      @Override protected void onStart() { super.onStart(); //設(shè)置回話監(jiān)聽回調(diào) getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback); }

      onResume()

      @Override protected void onResume() { super.onResume(); //This is the first onResume in a single life of the activity if (mInstallingTask == null) { //PackageInstaller:提供在設(shè)備上安裝、升級(jí)和刪除應(yīng)用程序的能力。 //這包括支持打包為單個(gè)“整體”APK 的應(yīng)用程序或打包為多個(gè)“拆分”APK 的應(yīng)用程序。 PackageInstaller installer = getPackageManager().getPackageInstaller(); //安裝Session的詳細(xì)信息 PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId); if (sessionInfo != null && !sessionInfo.isActive()) { //創(chuàng)建mInstallingTask并啟動(dòng) mInstallingTask = new InstallingAsyncTask(); mInstallingTask.execute(); } else { // 安裝完成后我們會(huì)收到廣播 //mCancelButton不允許點(diǎn)擊 mCancelButton.setEnabled(false); //Activity.setFinishOnTouchOutside():設(shè)置此活動(dòng)在其窗口邊界外觸摸 setFinishOnTouchOutside(false); } } }

      InstallingAsyncTask

      /** * Send the package to the package installer and then register a event result observer that * will call {@link #launchFinishBasedOnResult(int, int, String)} */ private final class InstallingAsyncTask extends AsyncTask { volatile boolean isDone; @Override protected PackageInstaller.Session doInBackground(Void... params) { PackageInstaller.Session session; try { //打開現(xiàn)有Session session = getPackageManager().getPackageInstaller().openSession(mSessionId); } catch (IOException e) { synchronized (this) { isDone = true; notifyAll(); } return null; } //設(shè)置暫存此會(huì)話的當(dāng)前進(jìn)度(0-1z之間)。 session.setStagingProgress(0); try { File file = new File(mPackageURI.getPath()); //輸入流in try (InputStream in = new FileInputStream(file)) { long sizeBytes = file.length(); //打開一個(gè)流以將 APK 文件寫入會(huì)話。 try (OutputStream out = session .openWrite("PackageInstaller", 0, sizeBytes)) { byte[] buffer = new byte[1024 * 1024]; //寫入文件 while (true) { int numRead = in.read(buffer); if (numRead == -1) { session.fsync(out); break; } if (isCancelled()) { session.close(); break; } //將 APK 文件通過 IO 流的形式寫入到 PackageInstaller.Session 中 out.write(buffer, 0, numRead); if (sizeBytes > 0) { float fraction = ((float) numRead / (float) sizeBytes); session.addProgress(fraction); } } } } return session; } catch (IOException | SecurityException e) { Log.e(LOG_TAG, "Could not write package", e); session.close(); return null; } finally { synchronized (this) { isDone = true; notifyAll(); } } } @Override protected void onPostExecute(PackageInstaller.Session session) { if (session != null) { //包已下載好,設(shè)置安裝提交廣播 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); // 調(diào)用 PackageInstaller.Session 的 commit 方法,進(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); } } } }

      其他沒啥好看的,咱么看看具體的session.commit

      PackageInstaller.commit()

      public void commit(@NonNull IntentSender statusReceiver) { try { mSession.commit(statusReceiver, false); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

      mSession 就是 IPackageInstallerSession 。這說明要通過 IPackageInstallerSession 來進(jìn)行進(jìn)程間的通信,最終會(huì)調(diào)用PackageInstallerSession 的 commit 方法

      PackageInstallerSession

      frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

      public class PackageInstallerSession extends IPackageInstallerSession.Stub { ... }

      commit()

      @Override public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) { if (hasParentSessionId()) { throw new IllegalStateException( "Session " + sessionId + " is a child of multi-package session " + mParentSessionId + " and may not be committed directly."); } if (!markAsSealed(statusReceiver, forTransfer)) { return; } //return true 多個(gè)包 if (isMultiPackage()) { ... } dispatchStreamValidateAndCommit(); }

      dispatchStreamValidateAndCommit()

      private void dispatchStreamValidateAndCommit() { // 通過 Handler 處理消息事件 mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget(); }

      mHandler()

      Handler mHandler = new Handler(looper, mHandlerCallback); private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_STREAM_VALIDATE_AND_COMMIT: handleStreamValidateAndCommit(); break; ... } return true; } };

      handleStreamValidateAndCommit

      private void handleStreamValidateAndCommit() { PackageManagerException unrecoverableFailure = null; // 這將跟蹤會(huì)話和任何子項(xiàng)是否已通過驗(yàn)證并準(zhǔn)備好進(jìn)入下一安裝階段 boolean allSessionsReady = false; try { allSessionsReady = streamValidateAndCommit(); } catch (PackageManagerException e) { unrecoverableFailure = e; } //多包,不是多包直接過 if (isMultiPackage()) { .... } if (!allSessionsReady) { return; } // 通過 Handler 處理MSG_INSTALL消息事件 mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); }

      mHandler()

      Handler mHandler = new Handler(looper, mHandlerCallback); private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { ... case MSG_INSTALL: handleInstall(); break; ... } return true; } };

      查看 mHnadler() 發(fā)現(xiàn) MSG_INSTALL 調(diào)用的是 handleInstall()。

      handleInstall()

      private void handleInstall() { ... //return true 會(huì)話被再次啟用。 if (params.isStaged) { mStagingManager.commitSession(this); destroyInternal(); dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null); return; } ... // 對(duì)于 multiPackage 會(huì)話,讀取鎖外的子會(huì)話, // 因?yàn)樽x取持有鎖的子會(huì)話可能會(huì)導(dǎo)致死鎖 (b/123391593)。 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); } }

      installNonStagedLocked()

      @GuardedBy("mLock") private void installNonStagedLocked(List childSessions) throws PackageManagerException { final PackageManagerService.ActiveInstallSession installingSession = makeSessionActiveLocked(); if (installingSession == null) { return; } //return true 多個(gè)包 if (isMultiPackage()) { List installingChildSessions = new ArrayList<>(childSessions.size()); ... mPm.installStage(installingChildSessions); } else { mPm.installStage(installingSession); } }

      這里不管不管怎么樣都會(huì)調(diào)用 mPm.installStage(installingChildSessions);

      mPm 就是系統(tǒng)服務(wù) PackageManagerService。

      PackageManagerService

      frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

      public class PackageManagerService extends IPackageManager.Stub implements PackageSender { }

      installStage()

      installStage 方法就是正式開始 apk 的安裝過程。這個(gè)過程包括兩大步:

      安裝包;

      裝載代碼

      ??Android 源碼解讀-安裝包的安裝過程 ??

      void installStage(ActiveInstallSession activeInstallSession) { ... final Message msg = mHandler.obtainMessage(INIT_COPY); //把之前傳入的 sessionParams 安裝信息,及其它信息封裝成 InstallParams final InstallParams params = new InstallParams(activeInstallSession); params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage", System.identityHashCode(msg.obj)); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(msg.obj)); mHandler.sendMessage(msg); } void installStage(List children) throws PackageManagerException { final Message msg = mHandler.obtainMessage(INIT_COPY); 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)); mHandler.sendMessage(msg); }

      MultiPackageInstallParams:多包安裝的容器,指的是一起提交的所有安裝會(huì)話和參數(shù)。

      這兩個(gè)方法很詳細(xì)就是把之前傳入的 sessionParams 安裝信息及其它信息封裝成 InstallParams(MultiPackageInstallParams)。

      mHandler 發(fā)送的消息 INIT_COPY 從名字上就知道是去初始化復(fù)制。

      mHandler()

      class PackageHandler extends Handler { PackageHandler(Looper looper) { super(looper); } public void handleMessage(Message msg) { try { doHandleMessage(msg); } finally { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } } 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"); params.startCopy(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } break; } ... } } }

      HandlerParams.startCopy()

      private abstract class HandlerParams { /** User handle for the user requesting the information or installation. */ private final UserHandle mUser; String traceMethod; int traceCookie; ... final void startCopy() { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this); handleStartCopy(); handleReturnCode(); } abstract void handleStartCopy(); abstract void handleReturnCode(); }

      startCopy(),里面有兩個(gè)抽象方法,咱只能去找他的實(shí)現(xiàn)類 InstallParams 里面的這兩個(gè)方法了。

      InstallParams

      class InstallParams extends HandlerParams { ... /* * 調(diào)用遠(yuǎn)程方法來獲取包信息和安裝位置值。 * 如果需要,根據(jù)默認(rèn)策略覆蓋安裝位置,然后根據(jù)安裝位置創(chuàng)建安裝參數(shù)。 */ public void handleStartCopy() { int ret = PackageManager.INSTALL_SUCCEEDED; // 表示文件已下載,不需要再次下載。 if (origin.staged) { // 設(shè)置安裝標(biāo)志位,決定是安裝在手機(jī)內(nèi)部存儲(chǔ)空間還是 sdcard 中 if (origin.file != null) { installFlags |= PackageManager.INSTALL_INTERNAL; } else { throw new IllegalStateException("Invalid stage location"); } } // 判斷安裝位置 final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0; final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; PackageInfoLite pkgLite = null; //解析給定的包并返回最少的細(xì)節(jié)。 pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, origin.resolvedPath, installFlags, packageAbiOverride); if (DEBUG_INSTANT && ephemeral) { Slog.v(TAG, "pkgLite for install: " + pkgLite); } /* * 如果我們的可用空間太少,請(qǐng)?jiān)诜艞壷皣L試釋放緩存。 */ if (!origin.staged && pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { // TODO: 釋放目標(biāo)設(shè)備上的磁盤空間 final StorageManager storage = StorageManager.from(mContext); //返回給定路徑被(Environment.getDataDirectory())認(rèn)為存儲(chǔ)空間不足的可用字節(jié)數(shù)。 final long lowThreshold = storage.getStorageLowBytes( Environment.getDataDirectory()); //返回:-1 計(jì)算安裝包大小有錯(cuò)誤 //返回其他:安裝包大小。 final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize( origin.resolvedPath, packageAbiOverride); if (sizeBytes >= 0) { try { //用于權(quán)限提升。 mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0); pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, origin.resolvedPath, installFlags, packageAbiOverride); } catch (InstallerException e) { Slog.w(TAG, "Failed to free cache", e); } } /* * 緩存刪除了我們下載安裝的文件。 * 用于存儲(chǔ)錯(cuò)誤 */ if (pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INVALID_URI) { pkgLite.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE; } } //安裝返回碼 if (ret == PackageManager.INSTALL_SUCCEEDED) { //指定推薦的安裝位置。 可以是其中之一 //RECOMMEND_INSTALL_INTERNAL 安裝在內(nèi)部存儲(chǔ)上, //RECOMMEND_INSTALL_EXTERNAL 安裝在外部媒體上, //RECOMMEND_FAILED_INSUFFICIENT_STORAGE 用于存儲(chǔ)錯(cuò)誤, //或 RECOMMEND_FAILED_INVALID_APK 解析錯(cuò)誤。 int loc = pkgLite.recommendedInstallLocation; ... } //創(chuàng)建安裝參數(shù) final InstallArgs args = createInstallArgs(this); mVerificationCompleted = true; mIntegrityVerificationCompleted = true; mEnableRollbackCompleted = true; mArgs = args; if (ret == PackageManager.INSTALL_SUCCEEDED) { final int verificationId = mPendingVerificationToken++; // 執(zhí)行安裝包驗(yàn)證(除非我們只是簡(jiǎn)單地移動(dòng)裝包)。 if (!origin.existing) { ... } //INSTALL_ENABLE_ROLLBACK 的標(biāo)志參數(shù)以指示應(yīng)為此安裝啟用回滾。 if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) { // TODO(ruhler) b/112431924: 在“move”的情況下不要這樣做? final int enableRollbackToken = mPendingEnableRollbackToken++; Trace.asyncTraceBegin( TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken); mPendingEnableRollback.append(enableRollbackToken, this); Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK); enableRollbackIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, enableRollbackToken); enableRollbackIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID, mSessionId); enableRollbackIntent.setType(PACKAGE_MIME_TYPE); enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //允許在啟動(dòng)完成前發(fā)送廣播。 在早期啟動(dòng)中提交分階段會(huì)話的 apk 部分時(shí)需要這樣做。 回滾管理器在啟動(dòng)過程中足夠早地注冊(cè)其接收器,以免錯(cuò)過廣播。 // 在早期啟動(dòng)中提交分階段會(huì)話的 apk 部分時(shí)需要這樣做。 // 回滾管理器在啟動(dòng)過程中足夠早地注冊(cè)其接收器,以免錯(cuò)過廣播。 enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM, android.Manifest.permission.PACKAGE_ROLLBACK_AGENT, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 等待回滾啟用的持續(xù)時(shí)間,以毫秒為單位 long rollbackTimeout = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS); if (rollbackTimeout < 0) { rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS; } final Message msg = mHandler.obtainMessage( ENABLE_ROLLBACK_TIMEOUT); msg.arg1 = enableRollbackToken; msg.arg2 = mSessionId; mHandler.sendMessageDelayed(msg, rollbackTimeout); } }, null, 0, null, null); mEnableRollbackCompleted = false; } } mRet = ret; } @Override void handleReturnCode() { if (mVerificationCompleted && mIntegrityVerificationCompleted && mEnableRollbackCompleted) { //INSTALL_DRY_RUN :installPackage 的標(biāo)志參數(shù),指示只應(yīng)驗(yàn)證包而不應(yīng)安裝包。 if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) { ... } if (mRet == PackageManager.INSTALL_SUCCEEDED) { //注釋1 mRet = mArgs.copyApk(); } //注釋2 processPendingInstall(mArgs, mRet); } } } }

      注釋1:mArgs 其實(shí)就是 InstallArgs ,而 InstallArgs 則是通過 createInstallArgs(this); 創(chuàng)建如下代碼: createInstallArgs(this)

      private InstallArgs createInstallArgs(InstallParams params) { if (params.move != null) { //處理現(xiàn)有已安裝應(yīng)用程序移動(dòng)的邏輯。 return new MoveInstallArgs(params); } else { //處理新應(yīng)用程序安裝的邏輯,包括復(fù)制和重命名邏輯。 return new FileInstallArgs(params); } }

      正常的流程下,createInstallArgs 返回的是 FileInstallArgs 對(duì)象。

      FileInstallArgs.copyApk()

      拷貝部分

      class FileInstallArgs extends InstallArgs { private File codeFile; private File resourceFile; // Example topology: // /data/app/com.example/base.apk // /data/app/com.example/split_foo.apk // /data/app/com.example/lib/arm/libfoo.so // /data/app/com.example/lib/arm64/libfoo.so // /data/app/com.example/dalvik/arm/base.apk@classes.dex /** New install */ FileInstallArgs(InstallParams params) { super(params); } /** Existing install */ FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) { super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY, null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0, PackageParser.SigningDetails.UNKNOWN, PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT, false, null /* parent */, DataLoaderType.NONE); this.codeFile = (codePath != null) ? new File(codePath) : null; this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null; } //執(zhí)行此處方法 int copyApk() { try { //就調(diào)用個(gè)doCopyApk(),接著往下看 return doCopyApk(); } finally { } } private int doCopyApk() { //表示文件已下載 if (origin.staged) { ... if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy"); //獲取安裝包路徑 codeFile = origin.file; resourceFile = origin.file; return PackageManager.INSTALL_SUCCEEDED; } try { final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; //創(chuàng)建路徑 final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); codeFile = tempDir; resourceFile = tempDir; } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } //將包復(fù)制到目標(biāo)位置(origin.file.getAbsolutePath())。 //返回狀態(tài)碼。注釋3 int ret = PackageManagerServiceUtils.copyPackage( origin.file.getAbsolutePath(), codeFile); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "無法復(fù)制安裝包"); return ret; } final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath()); final File libraryRoot = new File(codeFile, LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(codeFile); // 將 apk 中的動(dòng)態(tài)庫 .so 文件也拷貝到目標(biāo)路徑中。 ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, abiOverride, isIncremental); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } finally { IoUtils.closeQuietly(handle); } return ret; } }

      注釋3:PackageManagerServiceUtils.copyPackage() 這個(gè)看名字 就是調(diào)用 工具類 的 copyPackage 方法拷貝安裝包。具體咱們看代碼:

      PackageManagerServiceUtils.copyPackage()

      frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java

      /** * 將包復(fù)制到目標(biāo)位置。 * @param packagePath 要復(fù)制的包的絕對(duì)路徑。 * 可以是單個(gè)單一的 APK 文件,也可以是包含一個(gè)或多個(gè) APK 的集群目錄。 * @return 根據(jù)PackageManager 中的狀態(tài)返回狀態(tài)碼 */ public static int copyPackage(String packagePath, File targetDir) { if (packagePath == null) { return PackageManager.INSTALL_FAILED_INVALID_URI; } try { final File packageFile = new File(packagePath); final PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0); //下面有copyFile的源碼,咱一起看 copyFile(pkg.baseCodePath, targetDir, "base.apk"); if (!ArrayUtils.isEmpty(pkg.splitNames)) { for (int i = 0; i < pkg.splitNames.length; i++) { copyFile(pkg.splitCodePaths[i], targetDir, "split_" + pkg.splitNames[i] + ".apk"); } } return PackageManager.INSTALL_SUCCEEDED; } catch (PackageParserException | IOException | ErrnoException e) { Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } } 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); //將 source.getFD() 的內(nèi)容復(fù)制到targetFd。 //FileUtils:frameworks/base/core/java/android/os/FileUtils.java FileUtils.copy(source.getFD(), targetFd); } finally { IoUtils.closeQuietly(source); } }

      看到這里 最終安裝包在 data/app 目錄下以 base.apk 的方式保存(例如:/data/app/com.example/base.apk),至此安裝包拷貝工作就已經(jīng)完成。

      InstallParams

      接下來咱們看看 InstallParams 中 的 注釋2 processPendingInstall(mArgs, mRet); 也就是裝載部分。

      class InstallParams extends HandlerParams { ... @Override void handleReturnCode() { if (mVerificationCompleted && mIntegrityVerificationCompleted && mEnableRollbackCompleted) { ... if (mRet == PackageManager.INSTALL_SUCCEEDED) { //注釋1 mRet = mArgs.copyApk(); } //注釋2 processPendingInstall(mArgs, mRet); } } } }

      processPendingInstall()

      裝載部分

      private void processPendingInstall(final InstallArgs args, final int currentStatus) { //分包 if (args.mMultiPackageInstallParams != null) { args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus); } else { // PackageInstalledInfo res = createPackageInstalledInfo(currentStatus); //異步操作,因?yàn)榘惭b可能需要一段時(shí)間。 processInstallRequestsAsync( res.returnCode == PackageManager.INSTALL_SUCCEEDED, Collections.singletonList(new InstallRequest(args, res))); } }

      下面咱看看他的異步操作。

      processInstallRequestsAsync()

      private void processInstallRequestsAsync(boolean success, List installRequests) { mHandler.post(() -> { if (success) { for (InstallRequest request : installRequests) { // 預(yù)安裝操作,主要是檢查安裝包的狀態(tài),確保安裝環(huán)境正常,如果安裝環(huán)境有問題會(huì)清理拷貝文件 request.args.doPreInstall(request.installResult.returnCode); } synchronized (mInstallLock) { //真正的安裝階段 installPackagesTracedLI(installRequests); } for (InstallRequest request : installRequests) { request.args.doPostInstall( request.installResult.returnCode, request.installResult.uid); } } for (InstallRequest request : installRequests) { restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, new PostInstallData(request.args, request.installResult, null)); } }); }

      installPackagesTracedLI()

      @GuardedBy({"mInstallLock", "mLock"}) private void installPackagesTracedLI(List requests) { try { //添加跟蹤 Trace。 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages"); //調(diào)用 installPackageLI 方法進(jìn)行安裝。咱們接著看 installPackagesLI(requests); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } }

      installPackagesLI()

      @GuardedBy("mInstallLock") private void installPackagesLI(List requests) { ... boolean success = false; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI"); for (InstallRequest request : requests) { final PrepareResult prepareResult; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage"); //注釋1 //成功準(zhǔn)備好的安裝軟件包所需的數(shù)據(jù)集。這包括將用于掃描和協(xié)調(diào)包的數(shù)據(jù)。 prepareResult = preparePackageLI(request.args, request.installResult); } catch (PrepareFailure prepareFailure) { ... return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } ... } } }

      注釋1:preparePackageLI() 包含內(nèi)容過多咱們開始逐步講解。

      preparePackageLI()

      @GuardedBy("mInstallLock") private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res) throws PrepareFailure { final int installFlags = args.installFlags; final File tmpPackageFile = new File(args.getCodePath()); final boolean onExternal = args.volumeUuid != null; final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0); final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0); final boolean virtualPreload = ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0); @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE; ... ParsedPackage parsedPackage; //PackageParser2:PackageParser 的 v2 用于在服務(wù)中啟動(dòng)解析時(shí)使用,并且必須包含服務(wù)包含的狀態(tài)。 try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null, mPackageParserCallback)) { // 注釋1:pp.parsePackage()新包解析 parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false); AndroidPackageUtils.validatePackageDexMetadata(parsedPackage); } catch (PackageParserException e) { throw new PrepareFailure("Failed parse during installPackageLI", e); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } ... try { // 要么使用我們得到的,要么直接從APK解析 if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) { parsedPackage.setSigningDetails(args.signingDetails); } else { parsedPackage.setSigningDetails( ParsingPackageUtils.getSigningDetails(parsedPackage, false /* skipVerify */)); } } catch (PackageParserException e) { throw new PrepareFailure("Failed collect during installPackageLI", e); } //未使用v2簽名 if (instantApp && parsedPackage.getSigningDetails().signatureSchemeVersion < SignatureSchemeVersion.SIGNING_BLOCK_V2) { ... } boolean systemApp = false; boolean replace = false; synchronized (mLock) { // 檢查是否已安裝現(xiàn)有軟件包 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { ... } PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps != null) { if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); // 將簽名與最新庫版本的包設(shè)置進(jìn)行比較。 PackageSetting signatureCheckPs = ps; if (parsedPackage.isStaticSharedLibrary()) { ... } //注釋2:快速校驗(yàn)安裝包簽名 final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) { throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + parsedPackage.getPackageName() + " upgrade keys do not match the " + "previously installed version"); } } else { ... } if (ps.pkg != null) { systemApp = ps.pkg.isSystem(); } res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true); } // 注釋3:設(shè)置相關(guān)權(quán)限,生成、移植權(quán)限 int N = ArrayUtils.size(parsedPackage.getPermissions()); for (int i = N - 1; i >= 0; i--) { final ParsedPermission perm = parsedPackage.getPermissions().get(i); final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName()); ... } } if (args.move != null) { // 我們進(jìn)行了就地移動(dòng),因此 dex 已準(zhǔn)備就緒 ... } else { // 啟用 SCAN_NO_DEX 標(biāo)志以在稍后階段跳過 dexopt scanFlags |= SCAN_NO_DEX; try { final boolean extractNativeLibs = !AndroidPackageUtils.isLibrary(parsedPackage); PackageSetting pkgSetting; synchronized (mLock) { pkgSetting = mSettings.getPackageLPr(pkgName); } // 注釋4:生成安裝包Abi(Application binary interface,應(yīng)用二進(jìn)制接口) String abiOverride = (pkgSetting == null || TextUtils.isEmpty(pkgSetting.cpuAbiOverrideString) ? args.abiOverride : pkgSetting.cpuAbiOverrideString); boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null && pkgSetting.getPkgState().isUpdatedSystemApp(); AndroidPackage oldPackage = mPackages.get(pkgName); boolean isUpdatedSystemAppInferred = oldPackage != null && oldPackage.isSystem(); final Pair derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage, isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred, abiOverride, extractNativeLibs); derivedAbi.first.applyTo(parsedPackage); derivedAbi.second.applyTo(parsedPackage); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI", pme); throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI"); } } //注釋5:凍結(jié) 安裝包 final PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags, "installPackageLI"); boolean shouldCloseFreezerBeforeReturn = true; try { final AndroidPackage existingPackage; String renamedPackage = null; boolean sysPkg = false; int targetScanFlags = scanFlags; int targetParseFlags = parseFlags; final PackageSetting ps; final PackageSetting disabledPs; if (replace) { //更新包 ... } else { // 新包安裝 ... } // 解凍 安裝包 shouldCloseFreezerBeforeReturn = false; //返回成功準(zhǔn)備好的安裝包所需的數(shù)據(jù)集。 return new PrepareResult(replace, targetScanFlags, targetParseFlags, existingPackage, parsedPackage, replace /* clearCodeCache */, sysPkg, ps, disabledPs); } finally { res.freezer = freezer; if (shouldCloseFreezerBeforeReturn) { freezer.close(); } } }

      咱再回來看 installPackagesLI()

      installPackagesLI()

      @GuardedBy("mInstallLock") private void installPackagesLI(List requests) { ... try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI"); for (InstallRequest request : requests) { final PrepareResult prepareResult; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage"); //注釋1 //成功準(zhǔn)備好的安裝軟件包所需的數(shù)據(jù)集。這包括將用于掃描和協(xié)調(diào)包的數(shù)據(jù)。 prepareResult = preparePackageLI(request.args, request.installResult); ... try { //掃描包并返回新解析的包。 //出現(xiàn)錯(cuò)誤時(shí)返回null。 final ScanResult result = scanPackageTracedLI( prepareResult.packageToScan, prepareResult.parseFlags, prepareResult.scanFlags, System.currentTimeMillis(), request.args.user, request.args.abiOverride); ... } catch (PackageManagerException e) { request.installResult.setError("Scanning Failed.", e); return; } } //包掃描結(jié)果和相關(guān)請(qǐng)求詳細(xì)信息用于協(xié)調(diào)一個(gè)或多個(gè)包到系統(tǒng)的潛在添加。 ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs, installResults, prepareResults, mSharedLibraries, Collections.unmodifiableMap(mPackages), versionInfos, lastStaticSharedLibSettings); CommitRequest commitRequest = null; synchronized (mLock) { //ReconciledPackage:提交到內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)和磁盤所需的所有數(shù)據(jù)的容器。 //TODO:將此處包含的大部分?jǐn)?shù)據(jù)移動(dòng)到PackageSetting中進(jìn)行提交。 Map reconciledPackages; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages"); reconciledPackages = reconcilePackagesLocked( reconcileRequest, mSettings.mKeySetManagerService); } catch (ReconcileFailure e) { for (InstallRequest request : requests) { request.installResult.setError("Reconciliation failed...", e); } return; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages"); commitRequest = new CommitRequest(reconciledPackages, mUserManager.getUserIds()); commitPackagesLocked(commitRequest); success = true; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } //注釋2 executePostCommitSteps(commitRequest); } finally { ... } }

      注釋2:這里有個(gè) executePostCommitSteps() 方法,咱們一起來看看。

      executePostCommitSteps()

      /** * 成功安裝后,在提交完成并釋放包鎖后執(zhí)行剩余步驟。 * 這些通常更昂貴或需要調(diào)用 installd,這通常會(huì)鎖定 mLock。 */ private void executePostCommitSteps(CommitRequest commitRequest) { final ArraySet incrementalStorages = new ArraySet<>(); for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) { final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags & PackageManagerService.SCAN_AS_INSTANT_APP) != 0); final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg; final String packageName = pkg.getPackageName(); //注釋1:安裝并準(zhǔn)備 APP 數(shù)據(jù) prepareAppDataAfterInstallLIF(pkg); ... final boolean performDexopt = (!instantApp || Global.getInt(mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0) && !pkg.isDebuggable() && (!onIncremental) && dexoptOptions.isCompilationEnabled(); //優(yōu)化dex文件(實(shí)際為 dex2oat 操作,用來將 apk 中的 dex 文件轉(zhuǎn)換為 oat 文件) if (performDexopt) { // Compile the layout resources. if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts"); mViewCompiler.compileLayouts(pkg); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); ScanResult result = reconciledPkg.scanResult; PackageSetting realPkgSetting = result.existingSettingCopied ? result.request.pkgSetting : result.pkgSetting; if (realPkgSetting == null) { realPkgSetting = reconciledPkg.pkgSetting; } // Unfortunately, the updated system app flag is only tracked on this PackageSetting boolean isUpdatedSystemApp = reconciledPkg.pkgSetting.getPkgState() .isUpdatedSystemApp(); realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp); mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting, null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.getPackageUseInfoOrDefault(packageName), dexoptOptions); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } // Notify BackgroundDexOptService that the package has been changed. // If this is an update of a package which used to fail to compile, // BackgroundDexOptService will remove it from its denylist. // TODO: Layering violation BackgroundDexOptService.notifyPackageChanged(packageName); notifyPackageChangeObserversOnUpdate(reconciledPkg); } NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages); }

      咱們來看看 prepareAppDataAfterInstallLIF(pkg);

      prepareAppDataAfterInstallLIF()

      /** * 在安裝或升級(jí)后立即為給定的應(yīng)用程序準(zhǔn)備應(yīng)用程序數(shù)據(jù)。 * 此方法僅會(huì)小心地接觸為其安裝的用戶,并強(qiáng)制 restorecon 處理任何 seinfo 更改。 * * 驗(yàn)證目錄是否存在以及所有已安裝的應(yīng)用程序的所有權(quán)和標(biāo)簽是否正確。 * 如果所有權(quán)不匹配,它將嘗試通過擦除數(shù)據(jù)來恢復(fù)系統(tǒng)應(yīng)用程序; 第三方應(yīng)用程序數(shù)據(jù)保持不變。 * * 注意:為了避免死鎖,不要在持有mLock鎖的情況下調(diào)用這個(gè)方法 */ private void prepareAppDataAfterInstallLIF(AndroidPackage pkg) { final PackageSetting ps; synchronized (mLock) { ps = mSettings.mPackages.get(pkg.getPackageName()); mSettings.writeKernelMappingLPr(ps); } UserManagerInternal umInternal = mInjector.getUserManagerInternal(); StorageManagerInternal smInternal = mInjector.getStorageManagerInternal(); for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) { final int flags; if (umInternal.isUserUnlockingOrUnlocked(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { flags = StorageManager.FLAG_STORAGE_DE; } else { continue; } if (ps.getInstalled(user.id)) { // TODO:這里是我們關(guān)注的。咱們接著看 prepareAppDataLIF(pkg, user.id, flags); if (umInternal.isUserUnlockingOrUnlocked(user.id)) { // 在外部存儲(chǔ)上準(zhǔn)備應(yīng)用程序數(shù)據(jù); // 目前這用于設(shè)置由安裝程序正確創(chuàng)建的任何 OBB 目錄。 int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid())); smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid); } } } }

      在這里看看 prepareAppDataLIF()

      prepareAppDataLIF()

      private void prepareAppDataLIF(AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } prepareAppDataLeafLIF(pkg, userId, flags); }

      prepareAppDataLeafLIF()

      private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { if (DEBUG_APP_DATA) { Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x" + Integer.toHexString(flags)); } final PackageSetting ps; synchronized (mLock) { ps = mSettings.mPackages.get(pkg.getPackageName()); } final String volumeUuid = pkg.getVolumeUuid(); final String packageName = pkg.getPackageName(); final int appId = UserHandle.getAppId(pkg.getUid()); String pkgSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps); Preconditions.checkNotNull(pkgSeInfo); final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : ""); long ceDataInode = -1; try { ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo, pkg.getTargetSdkVersion()); } catch (InstallerException e) { if (pkg.isSystem()) { logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName + ", but trying to recover: " + e); destroyAppDataLeafLIF(pkg, userId, flags); try { //注釋1: 最終調(diào)用 系統(tǒng)服務(wù) Installer 安裝 ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo, pkg.getTargetSdkVersion()); logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); } catch (InstallerException e2) { logCriticalInfo(Log.DEBUG, "Recovery failed!"); } } else { Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e); } } if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) { mArtManagerService.prepareAppProfiles(pkg, userId, /* updateReferenceProfileContent= */ false); } if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { // TODO: mark this structure as dirty so we persist it! synchronized (mLock) { if (ps != null) { ps.setCeDataInode(ceDataInode, userId); } } } prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); }

      注釋1:mInstaller

      // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages // LOCK HELD. Can be called with mInstallLock held. @GuardedBy("mInstallLock") final Installer mInstaller;

      咱們看看 Installer

      Installer

      public class Installer extends SystemService { ... private volatile IInstalld mInstalld; 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)用 系統(tǒng)服務(wù) Installer 安裝

      至此整個(gè) apk 的安裝過程結(jié)束,實(shí)際上安裝成功之后,還會(huì)發(fā)送一個(gè) App 安裝成功的廣播 ACTION_PACKAGE_ADDED。手機(jī)桌面應(yīng)用注冊(cè)了這個(gè)廣播,當(dāng)接收到應(yīng)用安裝成功之后,就將 apk 的啟動(dòng) icon 顯示在桌面上。

      流程圖

      Android

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:基于鯤鵬服務(wù)器使用華為云源zabbix5.0安裝部署,監(jiān)控,郵件報(bào)警,自動(dòng)發(fā)現(xiàn)注冊(cè),分布式部署加代理等,一整套詳細(xì)操作 使用proxy, SNMP監(jiān)控
      下一篇:webpack基礎(chǔ)打包技術(shù)
      相關(guān)文章
      亚洲 欧洲 日韩 综合在线| 相泽南亚洲一区二区在线播放| 亚洲一本一道一区二区三区| 亚洲导航深夜福利| 精品亚洲永久免费精品| 国产亚洲色婷婷久久99精品| 国产日产亚洲系列最新| 精品亚洲成a人在线观看| 国产精品久久久久久亚洲小说| 亚洲一卡2卡3卡4卡5卡6卡| 亚洲日韩精品国产一区二区三区 | 亚洲伊人久久综合中文成人网| 亚洲国产成人久久笫一页| 亚洲国产精品自产在线播放| 亚洲精品第一国产综合精品99| 亚洲日本中文字幕一区二区三区| 亚洲中久无码不卡永久在线观看| 亚洲一级片免费看| 亚洲熟妇无码AV在线播放| 亚洲精品无码久久久久| 久久亚洲免费视频| 亚洲激情视频网站| 亚洲综合色一区二区三区| 亚洲国产成人综合精品| 伊在人亚洲香蕉精品区麻豆| 亚洲高清免费视频| 亚洲中文字幕在线第六区| 亚洲AV无码精品色午夜果冻不卡| 亚洲AV人无码综合在线观看| 日韩精品亚洲人成在线观看| 亚洲精品中文字幕乱码影院| 亚洲一级片在线观看| 亚洲啪AV永久无码精品放毛片| 国产亚洲欧美日韩亚洲中文色| 无码专区一va亚洲v专区在线 | 亚洲区精品久久一区二区三区| 亚洲资源最新版在线观看| 亚洲av中文无码字幕色不卡| 亚洲AV无码一区二区三区在线观看| 中文字幕中韩乱码亚洲大片| 亚洲精品狼友在线播放|