Installationsprozess der Android PMS APP

Warehouse-URL: http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

1. PMS-Installations-APP-Flussdiagramm

Fügen Sie hier eine Bildbeschreibung ein

2. Dateikopie

Flussdiagramm der PMS-Verarbeitungsinstallations-HandlerParams-Installationsparameter

Fügen Sie hier eine Bildbeschreibung einEinführung in die PackageManagerService.java#installStage-Methode

1. Ein InstallParams-Objekt wird erstellt.
2. Eine INIT_COPY-Nachricht wird erstellt und gesendet.
3. InstallParams erbt von HandlerParams und wird zum Aufzeichnen der Parameter für die Installation von Anwendungen verwendet. Es gibt eine Mitgliedsvariable mArgs in InstallParams, einem abstrakten Typ InstallArgs, der hauptsächlich zum Kopieren von APK verwendet wird. Zu den tatsächlichen Implementierungsklassen gehören: FileInstallArgs: Wird zum Abschließen der Installation von Nicht-ASEC-Anwendungen
verwendet. Der vollständige Name von ASEC ist Android
Sicherer externer Cache
MoveInstallArgs: Wird verwendet, um die mobile Installation der installierten App abzuschließen

void installStage(String packageName, File stagedDir, String stagedCid,
           IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
           String installerPackageName, int installerUid, UserHandle user,
           Certificate[][] certificates) {
    
    
       ...
       final Message msg = mHandler.obtainMessage(INIT_COPY);
       final int installReason = fixUpInstallReason(installerPackageName, installerUid,
               sessionParams.installReason);
       final InstallParams params = new InstallParams(origin, null, observer,
               sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
               verificationInfo, user, sessionParams.abiOverride,
               sessionParams.grantedRuntimePermissions, certificates, installReason);
       params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
       msg.obj = params;
       ...
       //发送信息拷贝INIT_COPY 信息
       mHandler.sendMessage(msg);
   }

PackageManagerService.java#PackageHandler

connectToService(): Der Dienst zum Überprüfen und Kopieren entfernbarer Dateien.
Senden Sie MCS_BOUND-Informationen, wodurch die Verarbeitung der ersten Installationsanforderung ausgelöst wird

       void doHandleMessage(Message msg) {
    
    
           switch (msg.what) {
    
    
               case INIT_COPY: {
    
    
                   HandlerParams params = (HandlerParams) msg.obj;
                   int idx = mPendingInstalls.size();
                   if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                   //mBound用于标识是否绑定了服务,默认值为false
                   if (!mBound) {
    
     
                       Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                               System.identityHashCode(mHandler));
                      //connectToService里面的DefaultContainerService是用于检查和复制可移动文件的服务
                       if (!connectToService()) {
    
      
                           Slog.e(TAG, "Failed to bind to media container service");
                           params.serviceError();
                           Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                   System.identityHashCode(mHandler));
                           if (params.traceMethod != null) {
    
    
                               Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
                                       params.traceCookie);
                           }
                           //绑定服务失败则return
                           return;
                       } else {
    
     
                           //绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
                           mPendingInstalls.add(idx, params);
                       }
                   } else {
    
      
                   //已经绑定服务
                       mPendingInstalls.add(idx, params);
                       if (idx == 0) {
    
       //5
                           //发送MCS_BOUND类型的消息,触发处理第一个安装请求
                           mHandler.sendEmptyMessage(MCS_BOUND);
                       }
                   }
                   break;
               }
               ....
               }
   }
}

MCS_BOUND-Prozessverarbeitung:

case MCS_BOUND: {
    
    
            if (mContainerService == null) {
    
             //判断是否已经绑定了服务
                if (!mBound) {
    
                //绑定服务的标识位,没有绑定成功
                      Slog.e(TAG, "Cannot bind to media container service");
                      for (HandlerParams params : mPendingInstalls) {
    
    
                          params.serviceError();
                          Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                        System.identityHashCode(params));
                          if (params.traceMethod != null) {
    
    
                          Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
                           params.traceMethod, params.traceCookie);
                          }
                          return;
                      }   
                          //绑定失败,清空安装请求队列
                          mPendingInstalls.clear();
                   } else {
    
                 // 绑定成功
                          //继续等待绑定服务
                          Slog.w(TAG, "Waiting to connect to media container service");
                   }
            } else if (mPendingInstalls.size() > 0) {
    
            //安装APK的队列
                          HandlerParams params = mPendingInstalls.get(0);   //安装队列有参数
                        if (params != null) {
    
    
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                    System.identityHashCode(params));
                            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                            if (params.startCopy()) {
    
                   //HandlerParams开始拷贝
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Checking for more work or unbind...");
                                 //如果APK安装成功,删除本次安装请求
                                if (mPendingInstalls.size() > 0) {
    
    
                                    mPendingInstalls.remove(0);
                                }
                                if (mPendingInstalls.size() == 0) {
    
      //安装队列没有参数
                                    if (mBound) {
    
                //已经绑定服务,需要发送一个解绑MCS_UNBIND的message
                                    //如果没有安装请求了,发送解绑服务的请求
                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                                "Posting delayed MCS_UNBIND");
                                        removeMessages(MCS_UNBIND);
                                        Message ubmsg = obtainMessage(MCS_UNBIND);
                                        sendMessageDelayed(ubmsg, 10000);
                                    }
                                } else {
    
    
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting MCS_BOUND for next work");
                                   //如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求       
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                        }else {
    
    
                        Slog.w(TAG, "Empty queue");
                    }
            break;
        }

PMS übernimmt das Kopieren von APP-Flussdiagrammen.
DefaultContainerService: die Klasse, die tatsächlich das Kopieren von APP-Dateien übernimmt

Fügen Sie hier eine Bildbeschreibung einPackageManagerService.java#HandlerParams#startCopy

1. Wenn die Anzahl der Installationsversuche das Vierfache überschreitet, entfernen Sie die installierten Listendaten.
2. handleStartCopy: //Kopieren Sie die APK-Datei.
3. handleReturnCode: //Starten Sie die Installation des APK

final boolean startCopy() {
    
    
           boolean res;
           try {
    
    
               if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
               //startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
               if (++mRetries > MAX_RETRIES) {
    
    
                   Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
                   mHandler.sendEmptyMessage(MCS_GIVE_UP);  //发送放弃安装信息
                   handleServiceError();
                   return false;
               } else {
    
    
                   handleStartCopy();      //复制APK文件
                   res = true;
               }
           } catch (RemoteException e) {
    
    
               if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
               mHandler.sendEmptyMessage(MCS_RECONNECT);
               res = false;
           }
           handleReturnCode();   //处理复制APK后的安装APK逻辑
           return res;
       }

PackageManagerService.java#InstallParams#handleStartCopy

1. Erhalten Sie einen Teil der APP-Installationsinformationen.
2. Erhalten Sie den Installationsort der APP.
3. Kopieren Sie die APP mit InstallArgs----> FileInstallArgs, kopieren Sie die APP---->DefaultContainerService und kopieren Sie die APP
InstallArgs als abstrakte Klasse, FileInstallArgs und MoveInstallArgs erben InstallArgs
FileInstallArgs: Ja Daten/Daten/Paketname (Systemanwendung)
MoveInstallArgs: Wird verwendet, um die Verschiebung des installierten APK zu verarbeiten

public void handleStartCopy() throws RemoteException {
    
    
       ...
       //确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)            
       final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
       final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
       final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
       PackageInfoLite pkgLite = null;
       if (onInt && onSd) {
    
    
         // APK不能同时安装在SD卡和Data分区
           Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
           ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
         //安装标志冲突,Instant Apps不能安装到SD卡中
       } else if (onSd && ephemeral) {
    
    
           Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
           ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
       } else {
    
    
            //获取APK的少量的信息
           pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                   packageAbiOverride);
           if (DEBUG_EPHEMERAL && ephemeral) {
    
    
               Slog.v(TAG, "pkgLite for install: " + pkgLite);
           }
       ...
       if (ret == PackageManager.INSTALL_SUCCEEDED) {
    
    
            //判断安装的位置
           int loc = pkgLite.recommendedInstallLocation;
           if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
    
    
               ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
           } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
    
    
               ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
           } 
           ...
           }else{
    
    
             loc = installLocationPolicy(pkgLite);     //确定APP安装的位置
             ...
           }
       }
       //根据InstallParams创建InstallArgs对象
       final InstallArgs args = createInstallArgs(this);    InstallArgs作用时:复制和重命名APK
       mArgs = args;
       if (ret == PackageManager.INSTALL_SUCCEEDED) {
    
    
              ...
           if (!origin.existing && requiredUid != -1
                   && isVerificationEnabled(
                         verifierUser.getIdentifier(), installFlags, installerUid)) {
    
    
                 ...
           } else{
    
    
               ret = args.copyApk(mContainerService, true);     // InstallArgs开始复制APP
           }
       }
       mRet = ret;
   }


private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
    
    
        ...
         try {
    
    
             final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
             //创建临时文件存储目录
             final File tempDir =
                     mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
             codeFile = tempDir;
             resourceFile = tempDir;
         } catch (IOException e) {
    
    
             Slog.w(TAG, "Failed to create copy file: " + e);
             return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
         }
         ...
         int ret = PackageManager.INSTALL_SUCCEEDED;
         ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
         ...
         return ret;
     }

3. Installieren Sie die APK

APP安装流程图

Fügen Sie hier eine Bildbeschreibung ein

1. Überprüfen Sie vor der Installation, ob die Umgebung zuverlässig ist. Andernfalls wird die kopierte APK-Datei gelöscht.
2. installPackageTracedLI ruft intern die installPackageLI-Methode von PMS auf, um APP zu installieren.
3. Erledigen Sie den Nachinstallationsvorgang. Wenn die Installation nicht erfolgreich ist, löschen Sie die Installationsverzeichnisse und Dateien.

  final boolean startCopy() {
    
    
    ......
    handleStartCopy();  //APP文件复制拷贝
    .....
    //开始安装APP
  handleReturnCode();
  }
   void handleReturnCode() {
    
    
        ........
        if (mArgs != null) {
    
    
        processPendingInstall(mArgs, mRet);
      }
    }

    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    
    
        mHandler.post(new Runnable() {
    
    
            public void run() {
    
    
                mHandler.removeCallbacks(this);
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.setReturnCode(currentStatus);
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = null;
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
    
    
                    //安装前处理
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
    
    
                        //开始安装
                        installPackageTracedLI(args, res);
                    }
                    //安装后收尾
                    args.doPostInstall(res.returnCode, res.uid);
                }
              ...
            }
        });
    }

Je suppose que tu aimes

Origine blog.csdn.net/qq_24252589/article/details/131353190
conseillé
Classement