android 9.x PKMS(一)adb install安装apk流程

引言

最近手上有银联商务招标的需求,涉及到apk的验签策略,梳理一遍adb install的流程。
每次看完源码,做完需求,后面就慢慢忘记代码流程了,遂写成博客记录下来。

流程图

开始写博客,不太会使用Flowchart流程图,从博友那借用了一张。
c++到java的流程没看懂,流程图有点对不上android9.x的流程,将就着看吧。
出处:https://blog.csdn.net/chishi199433/article/details/103925833
(侵权必删)
在这里插入图片描述adb inatsll ***.apk 命令对应的代码在/system/core/adb/commandline.cpp里面

int adb_commandline(int argc, const char** argv) {
	.......
	//adb其他命令,pull,push,shell,ls...
	.......
	else if (!strcmp(argv[0], "install")) {
         if (argc < 2) return syntax_error("install requires an argument");
         if (_use_legacy_install()) {
             return install_app_legacy(argc, argv);
          }
          return install_app(argc, argv);
     }
}

调用到install_app_legacy()函数

static int install_app_legacy(int argc, const char** argv) {
	.......
	.......
	
     return pm_command(argc, argv);
}

调用到pm_command()函数

2045  static int pm_command(int argc, const char** argv) {
2046      std::string cmd = "pm";
2047  
2048      while (argc-- > 0) {
2049          cmd += " " + escape_arg(*argv++);
2050      }
2051  
2052      return send_shell_command(cmd, false);
2053  }

调用到send_shell_command()函数,看了下里面的逻辑,没看懂怎么调用到java层。
不死心想要弄清楚c++到java的流程,从java层开始逆向分析。

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

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ShellCallback callback,
            ResultReceiver resultReceiver) {
	+   Thread.dumpStack();
        (new PackageManagerShellCommand(this)).exec(
                this, in, out, err, args, callback, resultReceiver);
    }

通过Thread.dumpStack()打印调用方法栈,编译,push Service.jar之后查看log

03-04 16:40:27.204   907  1021 W System.err: java.lang.Exception: Stack trace
03-04 16:40:27.205   907  1021 W System.err: 	at java.lang.Thread.dumpStack(Thread.java:1348)
03-04 16:40:27.205   907  1021 W System.err: 	at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21781)
03-04 16:40:27.205   907  1021 W System.err: 	at android.os.Binder.shellCommand(Binder.java:634)
03-04 16:40:27.205   907  1021 W System.err: 	at android.os.Binder.onTransact(Binder.java:532)
03-04 16:40:27.205   907  1021 W System.err: 	at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2796)
03-04 16:40:27.205   907  1021 W System.err: 	at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3964)
03-04 16:40:27.205   907  1021 W System.err: 	at android.os.Binder.execTransact(Binder.java:731)

看到熟悉的android.os.Binder和onTransact(),恍然大悟,原来是用的Binder机制,不懂的同学建议学习Binder的相关知识

继续从PackageManagerService.java的onShellCommand()方法开始分析,exec()调用的是父类ShellCommand.java的方法
frameworks/base/core/java/android/os/ShellCommand.java

79      public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
80              String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
81          String cmd;
82          int start;
83          if (args != null && args.length > 0) {
84              cmd = args[0];
85              start = 1;
86          } else {
87              cmd = null;
88              start = 0;
89          }
90          init(target, in, out, err, args, callback, start);
91          mCmd = cmd;
92          mResultReceiver = resultReceiver;
93  		.......
			.......
101          int res = -1;
102          try {
103              res = onCommand(mCmd);
104              if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
105          } catch (SecurityException e) {
106              PrintWriter eout = getErrPrintWriter();
107              eout.println("Security exception: " + e.getMessage());
108              eout.println();
109              e.printStackTrace(eout);
110          } catch (Throwable e) {
111             .......
				.......
119          } finally {
120              .......
				.......
130              }
131          }
132          if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
133          return res;
134      }

调用到onCommand()方法

 public abstract int onCommand(String cmd);

看到abstract字段,就知道是子类继承,重写方法
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            return handleDefaultCommands(cmd);
        }

        final PrintWriter pw = getOutPrintWriter();
        try {
            switch(cmd) {
				..........
				..........
                case "install":
                    return runInstall();
                ..........
                ..........
            }
        } catch (RemoteException e) {
            pw.println("Remote exception: " + e);
        }
        return -1;
    }

调用到runInstall()方法,主要流程是doCreateSession(),doWriteSplit(),doCommitSession()这三个方法

    901      private int runInstall() throws RemoteException {
902          final PrintWriter pw = getOutPrintWriter();
903          final InstallParams params = makeInstallParams();
904          final String inPath = getNextArg();
905  
906          setParamsSize(params, inPath);
			//创建sessionId 
907          final int sessionId = doCreateSession(params.sessionParams,
908                  params.installerPackageName, params.userId);
909          boolean abandonSession = true;
910          try {
911              if (inPath == null && params.sessionParams.sizeBytes == -1) {
912                  pw.println("Error: must either specify a package size or an APK file");
913                  return 1;
914              }
915              if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
916                      false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
917                  return 1;
918              }
919              if (doCommitSession(sessionId, false /*logSuccess*/)
920                      != PackageInstaller.STATUS_SUCCESS) {
921                  return 1;
922              }
923              abandonSession = false;
924              pw.println("Success");
925              return 0;
926          } finally {
927              if (abandonSession) {
928                  try {
929                      doAbandonSession(sessionId, false /*logSuccess*/);
930                  } catch (Exception ignore) {
931                  }
932              }
933          }
934      }

doCreateSession()

doCreateSession()方法去创建PackageInstallerSession对象,返回sessionId。

			final IPackageManager mInterface;

2406      private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2407              throws RemoteException {
2408          userId = translateUserId(userId, true /*allowAll*/, "runInstallCreate");
2409          if (userId == UserHandle.USER_ALL) {
2410              userId = UserHandle.USER_SYSTEM;
2411              params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2412          }
2413  
2414          final int sessionId = mInterface.getPackageInstaller()
2415                  .createSession(params, installerPackageName, userId);
2416          return sessionId;
2417      }

看到IPackageManager mInterface,Binder机制,找IPackageManager 的实现类
/frameworks/base/core/java/android/app/ApplicationPackageManager.java

2454      @Override
2455      public PackageInstaller getPackageInstaller() {
2456          synchronized (mLock) {
2457              if (mInstaller == null) {
2458                  try {
2459                      mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
2460                              mContext.getPackageName(), mContext.getUserId());
2461                  } catch (RemoteException e) {
2462                      throw e.rethrowFromSystemServer();
2463                  }
2464              }
2465              return mInstaller;
2466          }
2467      }

mInterface.getPackageInstaller()返回PackageInstaller对象
/frameworks/base/core/java/android/content/pm/PackageInstaller.java

 		private final IPackageInstaller mInstaller;
 		
		 public int createSession(@NonNull SessionParams params) throws IOException {
326          try {
327              final String installerPackage;
328              if (params.installerPackageName == null) {
329                  installerPackage = mInstallerPackageName;
330              } else {
331                  installerPackage = params.installerPackageName;
332              }
333  
334              return mInstaller.createSession(params, installerPackage, mUserId);
335          } catch (RuntimeException e) {
336              ExceptionUtils.maybeUnwrapIOException(e);
337              throw e;
338          } catch (RemoteException e) {
339              throw e.rethrowFromSystemServer();
340          }
341      }

看到IPackageInstaller mInstaller,Binder机制,找IPackageInstaller 的实现类
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java

401      @Override
402      public int createSession(SessionParams params, String installerPackageName, int userId) {
403          try {
404              return createSessionInternal(params, installerPackageName, userId);
405          } catch (IOException e) {
406              throw ExceptionUtils.wrap(e);
407          }
408      }
409  
410      private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
411              throws IOException {
412         	..........
				//权限检查
				//根据调用者的UID调整installFlags
				//安装位置处理,不能安装在外部存储
				//设置app图标大小
440  			..........
508          final int sessionId;
509          final PackageInstallerSession session;
510          synchronized (mSessions) {
511              // Sanity check that installer isn't going crazy
				//检查mSessions数组里面PackageInstallerSession对象的数量,最大数量1024
512              final int activeCount = getSessionCount(mSessions, callingUid);
513              if (activeCount >= MAX_ACTIVE_SESSIONS) {
514                  throw new IllegalStateException(
515                          "Too many active sessions for UID " + callingUid);
516              }
517              final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
518              if (historicalCount >= MAX_HISTORICAL_SESSIONS) {
519                  throw new IllegalStateException(
520                          "Too many historical sessions for UID " + callingUid);
521              }
				//生成sessionId
523              sessionId = allocateSessionIdLocked();
524          }
525  
526          final long createdMillis = System.currentTimeMillis();
527          // We're staging to exactly one location
528          File stageDir = null;
529          String stageCid = null;
530          if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
531              final boolean isInstant =
532                      (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
				//data下面新建vmdl0123456789.tmp临时目录
533              stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
534          } else {
535              stageCid = buildExternalStageCid(sessionId);
536          }
537  		//构建PackageInstallerSession对象
538          session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
539                  mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
540                  params, createdMillis, stageDir, stageCid, false, false);
541  
542          synchronized (mSessions) {
				//使用数组来存放sessionId和PackageInstallerSession对象
543              mSessions.put(sessionId, session);
544          }
545  		//创建成功回调,回调给实现了IPackageInstallerCallback接口的类
546          mCallbacks.notifySessionCreated(session.sessionId, session.userId);
547          writeSessionsAsync();
548          return sessionId;
549      }

allocateSessionIdLocked()方法里面去生成sessionId,我们可以写成自己想要sessionId。

    private File buildStageDir(String volumeUuid, int sessionId, boolean isEphemeral) {
        final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
        return new File(stagingDir, "vmdl" + sessionId + ".tmp");
    }

这里生成/data/app/vmdl01234567890.tmp文件夹,用来存放临时apk文件

再来看writeSessionsAsync()方法,将PackageInstallerSession信息写入mSessionsFile文件

        mSessionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
                "package-session");
        mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
        mSessionsDir.mkdirs();
	..........
	..........
    private void writeSessionsAsync() {
        IoThread.getHandler().post(new Runnable() {
            @Override
            public void run() {
                synchronized (mSessions) {
                    writeSessionsLocked();
                }
            }
        });
    }
	.........
	.........
	    @GuardedBy("mSessions")
    private void writeSessionsLocked() {
        if (LOGD) Slog.v(TAG, "writeSessionsLocked()");

        FileOutputStream fos = null;
        try {
            fos = mSessionsFile.startWrite();

            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_SESSIONS);
            final int size = mSessions.size();
            for (int i = 0; i < size; i++) {
                final PackageInstallerSession session = mSessions.valueAt(i);
                session.write(out, mSessionsDir);
            }
            out.endTag(null, TAG_SESSIONS);
            out.endDocument();

            mSessionsFile.finishWrite(fos);
        } catch (IOException e) {
            if (fos != null) {
                mSessionsFile.failWrite(fos);
            }
        }
    }

文件路径是data/system/install_sessions.xml,里面的内容:

*******:/ # cat data/system/install_sessions.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<sessions>
<session sessionId="1234567890" userId="0" installerUid="0" createdMillis="1614864398329" sessionStageDir="/data/app/vmdl1234567890.tmp" prepared="true" sealed="false" mode="1" installFlags="114" installLocation="1" sizeBytes="4737146" originatingUid="-1" installRason="0" />
</sessions>

/data/app/vmdl1234567890.tmp里面的1234567890就是我写死的sessionId

doWriteSplit()

继续往下看,来到doWriteSplit()方法,将apk的数据写入到/data/app/vmdl1234567890.tmp/base.apk中

private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
            boolean logSuccess) throws RemoteException {
		..........
		..........
        PackageInstaller.Session session = null;
        try {
            session = new PackageInstaller.Session(
                    mInterface.getPackageInstaller().openSession(sessionId));
            session.write(splitName, 0, sizeBytes, fd);

            if (logSuccess) {
                pw.println("Success: streamed " + sizeBytes + " bytes");
            }
            return 0;
        } catch (IOException e) {
            getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
            return 1;
        } finally {
            IoUtils.closeQuietly(session);
        }
    }

doCommitSession()

继续往下看,来到doCommitSession()方法

    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        PackageInstaller.Session session = null;
        try {
        	//通过sessionId获取Session对象
            session = new PackageInstaller.Session(
                    mInterface.getPackageInstaller().openSession(sessionId));

            // 仔细检查所有.dm文件是否均匹配apk。
            //(安装程序不支持独立的.dm文件,因此不会对其进行处理。) 
            try {
                DexMetadataHelper.validateDexPaths(session.getNames());
            } catch (IllegalStateException | IOException e) {
                pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
            }

            final LocalIntentReceiver receiver = new LocalIntentReceiver();
            //调用PackageInstaller的commit()方法,receiver是获取安装结果的句柄
            session.commit(receiver.getIntentSender());

            // 等待300秒获取安装结果
            final Intent result = receiver.getResult(300);
            if (result == null) {
                pw.println("Failure [install timeout]");
                return PackageInstaller.STATUS_FAILURE;
            }

            int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                    PackageInstaller.STATUS_FAILURE);
            if (status == PackageInstaller.STATUS_SUCCESS) {
                if (logSuccess) {
                    pw.println("Success");
                }
            } else {
                pw.println("Failure ["
                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
                status = result.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
                    PackageManager.INSTALL_FAILED_ABORTED);
            }
            return status;
        } finally {
            IoUtils.closeQuietly(session);
        }
    }

result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);获取安装结果,结果是在哪里put进去的呢
继续往下看,session.commit()调用PackageInstaller的commit()方法

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

实际上调用到PackageInstallerSession类里面的commit()方法

    @Override
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
        Preconditions.checkNotNull(statusReceiver);

        final boolean wasSealed;
        synchronized (mLock) {
            assertCallerIsOwnerOrRootLocked();
            assertPreparedAndNotDestroyedLocked("commit");

            final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
                    mContext, statusReceiver, sessionId,
                    isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
            mRemoteObserver = adapter.getBinder();
           ..........
		   .........
            wasSealed = mSealed;
            if (!mSealed) {
                try {
                    sealAndValidateLocked();
                } catch (IOException e) {
                    throw new IllegalArgumentException(e);
                } catch (PackageManagerException e) {
                    // Do now throw an exception here to stay compatible with O and older
                    destroyInternal();
                    dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
                    return;
                }
            }

            // Client staging is fully done at this point
            mClientProgress = 1f;
            computeProgressLocked(true);

            // This ongoing commit should keep session active, even though client
            // will probably close their end.
            mActiveCount.incrementAndGet();

            mCommitted = true;
            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
        }

        if (!wasSealed) {
            // Persist the fact that we've sealed ourselves to prevent
            // mutations of any hard links we create. We do this without holding
            // the session lock, since otherwise it's a lock inversion.
            mCallback.onSessionSealedBlocking(this);
        }
    }

statusReceiver对象用来初始化PackageInstallObserverAdapter对象
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java

			//apk临时文件删除回调,从PackageManagerService.java的deletePackageVersioned()方法回调过来的
847          @Override
848          public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
849              if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null) {
850                  NotificationManager notificationManager = (NotificationManager)
851                          mContext.getSystemService(Context.NOTIFICATION_SERVICE);
852                  notificationManager.notify(basePackageName,
853                          SystemMessage.NOTE_PACKAGE_STATE,
854                          mNotification);
855              }
856              final Intent fillIn = new Intent();
857              fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
858              fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
859                      PackageManager.deleteStatusToPublicStatus(returnCode));
860              fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
861                      PackageManager.deleteStatusToString(returnCode, msg));
862              fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
863              try {
864                  mTarget.sendIntent(mContext, 0, fillIn, null, null);
865              } catch (SendIntentException ignored) {
866              }
867          }
			.........
			.........
877          public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
878                  boolean showNotification, int userId) {
879              mContext = context;
880              mTarget = target;
881              mSessionId = sessionId;
882              mShowNotification = showNotification;
883              mUserId = userId;
884          }

statusReceiver用来初始化mTarget, mTarget.sendIntent()方法里面放入Intent对象,PackageInstaller.EXTRA_STATUS的值就是在这里put的(PackageInstallerService.java的其他方法里面也有put这个值)。
继续往下看,来到PackageInstallerSession类里面commit()的sealAndValidateLocked()方法,锁定会话防止被修改,并进行apk的验签,流程后面再写博客分析

882      @GuardedBy("mLock")
883      private void sealAndValidateLocked() throws PackageManagerException, IOException {
884          assertNoWriteFileTransfersOpenLocked();
885          assertPreparedAndNotDestroyedLocked("sealing of session");
886          //获取安装包信息
887          final PackageInfo pkgInfo = mPm.getPackageInfo(
888                  params.appPackageName, PackageManager.GET_SIGNATURES
889                          | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
890  
891          resolveStageDirLocked();
893          mSealed = true;
894  
895          // 验证packageName,versionCode和证书的一致性。 
			//初始化预处理文件列表, mResolvedInstructionSets,mResolvedNativeLibPaths,mResolvedInstructionSets,	       mResolvedInheritedFiles等。
898          try {
899              validateInstallLocked(pkgInfo);
900          } catch (PackageManagerException e) {
901              throw e;
902          } catch (Throwable e) {
903              // Convert all exceptions into package manager exceptions as only those are handled
904              // in the code above
905              throw new PackageManagerException(e);
906          }
908          // Read transfers from the original owner stay open, but as the session's data
909          // cannot be modified anymore, there is no leak of information.
910      }

继续往下看,来到PackageInstallerSession类里面commit()里的这段代码,mHandler.obtainMessage(MSG_COMMIT).sendToTarget(),handler发送MSG_COMMIT消息,找到接收处理消息的地方

291                  case MSG_COMMIT:
292                      synchronized (mLock) {
293                          try {
294                              commitLocked();
295                          } catch (PackageManagerException e) {
296                              final String completeMsg = ExceptionUtils.getCompleteMessage(e);
297                              Slog.e(TAG,
298                                      "Commit of session " + sessionId + " failed: " + completeMsg);
299                              destroyInternal();// 删除文件描述符,删除文件桥接
												//mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());删除安装包
												//最后调用到native服务InstalldNativeService.cpp里面的rmPackageDir()方法
												
								//Session派发完成,通过注册的监听回调
								//PackageInstallerService.java:
								//PackageInstallerService.InternalCallback的onSessionFinished()方法
								//
								//IPackageInstallObserver2的onPackageInstalled()方法
300                              dispatchSessionFinished(e.error, completeMsg, null);
301                          }
302                      }
304                      break;

主要来看看commitLocked()方法

    @GuardedBy("mLock")
    private void commitLocked()
            throws PackageManagerException {
		..........
		..........
		//运行时权限确认弹窗
        if (needToAskForPermissionsLocked()) {
            // 用户需要接受权限; 向安装人员提供可以使用户参与的意图。 
            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
            intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
            try {
                mRemoteObserver.onUserActionRequired(intent);
            } catch (RemoteException ignored) {
            }

            // Commit was keeping session marked as active until now; release
            // that extra refcount so session appears idle.
            closeInternal(false);
            return;
        }

        // 从现有安装继承未覆盖的所有程序包和本机库。 
        if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
            try {
                final List<File> fromFiles = mResolvedInheritedFiles;
                final File toDir = resolveStageDirLocked();

                if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                    throw new IllegalStateException("mInheritedFilesBase == null");
                }

                if (isLinkPossible(fromFiles, toDir)) {
                    if (!mResolvedInstructionSets.isEmpty()) {
                        final File oatDir = new File(toDir, "oat");
                        //生成oat包,最后调用到InstalldNativeService.cpp的createOatDir()方法
                        createOatDirs(mResolvedInstructionSets, oatDir);
                    }
                    // 预创建lib dirs以在必要时进行链接,mResolvedNativeLibPaths在validateInstallLocked(pkgInfo)中初始化完成
                    if (!mResolvedNativeLibPaths.isEmpty()) {
                        for (String libPath : mResolvedNativeLibPaths) {
                            // "/lib/arm64" -> ["lib", "arm64"]
                            final int splitIndex = libPath.lastIndexOf('/');
                            if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
                                Slog.e(TAG, "Skipping native library creation for linking due to "
                                        + "invalid path: " + libPath);
                                continue;
                            }
                            final String libDirPath = libPath.substring(1, splitIndex);
                            final File libDir = new File(toDir, libDirPath);
                            if (!libDir.exists()) {
                                NativeLibraryHelper.createNativeLibrarySubdir(libDir);
                            }
                            final String archDirPath = libPath.substring(splitIndex + 1);
                            NativeLibraryHelper.createNativeLibrarySubdir(
                                    new File(libDir, archDirPath));
                        }
                    }
                    //建立软链接
                    linkFiles(fromFiles, toDir, mInheritedFilesBase);
                } else {
                    // TODO: this should delegate to DCS so the system process
                    // avoids holding open FDs into containers.
                    copyFiles(fromFiles, toDir);
                }
            } catch (IOException e) {
                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                        "Failed to inherit existing install", e);
            }
        }

        // 更新安装进度
        mInternalProgress = 0.5f;
        computeProgressLocked(true);

        // 解压本地库
        extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());

        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
            @Override
            public void onUserActionRequired(Intent intent) {
                throw new IllegalStateException();
            }

            @Override
            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                    Bundle extras) {
                destroyInternal();
                dispatchSessionFinished(returnCode, msg, extras);
            }
        };
		........
		........
		//调用PackageManagerService服务的installStage()方法进行安装
        mRelinquished = true;
        mPm.installStage(mPackageName, stageDir, localObserver, params,
                mInstallerPackageName, mInstallerUid, user, mSigningDetails);
    }

又回到PackageManagerService服务里面,继续看installStage()方法

void installStage(String packageName, File stagedDir,
            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
            String installerPackageName, int installerUid, UserHandle user,
            PackageParser.SigningDetails signingDetails) {
        if (DEBUG_INSTANT) {
            if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
                Slog.d(TAG, "Ephemeral install of " + packageName);
            }
        }
        //签名信息
        final VerificationInfo verificationInfo = new VerificationInfo(
                sessionParams.originatingUri, sessionParams.referrerUri,
                sessionParams.originatingUid, installerUid);
		//初始化OriginInfo对象,成员变量staged为true
        final OriginInfo origin = OriginInfo.fromStagedFile(stagedDir);

        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, signingDetails, installReason);
        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);
    }

构建HandlerParams对象,然后通过handler发送INIT_COPY消息,记住这里发送的是InstallParams

				case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    //是否绑定DefaultContainerService服务,该服务属于独立的进程
                    if (!mBound) {
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        
                        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;
                        } else {
                            //绑定服务成功,将安装信息add进待安装列表
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                        mPendingInstalls.add(idx, params);
                        //如果mPendingInstalls的长度为0,发送MCS_BOUND消息
                        if (idx == 0) {
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }

继续看MCS_BOUND消息的处理过程

				case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                   		//初始化mContainerService
                        mContainerService = (IMediaContainerService) msg.obj;
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                    }
                    if (mContainerService == null) {
                        if (!mBound) {
                            //没有绑定DefaultContainerService服务
                            Slog.e(TAG, "Cannot bind to media container service");
                            for (HandlerParams params : mPendingInstalls) {
                                // Indicate service bind error
                                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);
                                }
                            }
                            mPendingInstalls.clear();
                        } else {
                            Slog.w(TAG, "Waiting to connect to media container service");
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        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");
                            进行APK文件的拷贝
                            if (params.startCopy()) {
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Checking for more work or unbind...");
                                //删除执行成功的安装请求
                                if (mPendingInstalls.size() > 0) {
                                    mPendingInstalls.remove(0);
                                }
                                if (mPendingInstalls.size() == 0) {
                                    if (mBound) {
                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                                "Posting delayed MCS_UNBIND");
                                        removeMessages(MCS_UNBIND);
                                        Message ubmsg = obtainMessage(MCS_UNBIND);
                                        //延迟10秒解绑DefaultContainerService服务
                                        sendMessageDelayed(ubmsg, 10000);
                                    }
                                } else {
                                    //mPendingInstalls队列中还有其他请求,发送MCS_BOUND消息触发下一次安装的处理
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting MCS_BOUND for next work");
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                        }
                    } else {
                        Slog.w(TAG, "Empty queue");
                    }
                    break;
                }

来看params.startCopy()这行代码,调用到HandlerParams.java的startCopy方法

final boolean startCopy() {
            boolean res;
            try {
                if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);

                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();
                    res = true;
                }
            } catch (RemoteException e) {
                if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
                mHandler.sendEmptyMessage(MCS_RECONNECT);
                res = false;
            }
            //处理拷贝操作返回值
            handleReturnCode();
            return res;
        }

执行到handleStartCopy()方法,调用到InstallParams.java覆写的handleStartCopy()方法

public void handleStartCopy() throws RemoteException {
            int ret = PackageManager.INSTALL_SUCCEEDED;
            //前面是通过Session拷贝的apk,这里为true
            if (origin.staged) {
                if (origin.file != null) {
                    installFlags |= PackageManager.INSTALL_INTERNAL;
                    installFlags &= ~PackageManager.INSTALL_EXTERNAL;
                } else {
                    throw new IllegalStateException("Invalid stage location");
                }
            }
			//这里onSd=false,onInt=true
            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) {
                // Check if both bits are set.
                Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else if (onSd && ephemeral) {
                Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else {
                pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                        packageAbiOverride);

                if (DEBUG_INSTANT && ephemeral) {
                    Slog.v(TAG, "pkgLite for install: " + pkgLite);
                }
                .........
                //空间不足时,尝试释放空间,删除不必要的文件
                .........
            }
			........
			........
			//创建用于实际拷贝apk文件的InstallArgs对象
            final InstallArgs args = createInstallArgs(this);
            mArgs = args;

            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                // TODO: http://b/22976637
                // 使用system user来验证应用程序
                UserHandle verifierUser = getUser();
                if (verifierUser == UserHandle.ALL) {
                    verifierUser = UserHandle.SYSTEM;
                }
                //确定我们是否已安装任何软件包验证程序。 如果这样做,那么我们将推迟他们对软件包进行验证。 
                final int requiredUid = mRequiredVerifierPackage == null ? -1
                        : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                                verifierUser.getIdentifier());
                final int installerUid =
                        verificationInfo == null ? -1 : verificationInfo.installerUid;
                if (!origin.existing && requiredUid != -1
                        && isVerificationEnabled(
                                verifierUser.getIdentifier(), installFlags, installerUid)) {
                    ........
                    ........
                } else {
                    //没有启用包验证,因此请立即启动远程调用以使用临时文件启动复制。 
                    ret = args.copyApk(mContainerService, true);
                }
            }
            mRet = ret;
        }

从这里我们可以看到APK的拷贝工作又交给InstallArgs对象进行处理,根据InstallParams中的参数来创建不同的对象,直接看FileInstallArgs中的copyApk()方法

        int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
            try {
                return doCopyApk(imcs, temp);
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

        private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
            if (origin.staged) {//true,直接返回
                if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
                codeFile = origin.file;
                resourceFile = origin.file;
                return PackageManager.INSTALL_SUCCEEDED;
            }
			........
			........
        }

9.0版本中通过Session拷贝apk,在doCopyApk()之前,apk就已经拷贝完成。
接下来看apk拷贝之后的操作handleReturnCode()

		@Override
        void handleReturnCode() {
            // 如果mArgs为null,则无法访问MCS。 重新连接时,它将再次尝试安装
            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对象解析currentStatus参数
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.setReturnCode(currentStatus);
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = null;
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                	//安装前,res.returnCode不等于PackageManager.INSTALL_SUCCEEDED时,清理残留文件
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                    	//apk安装
                        installPackageTracedLI(args, res);
                    }
                    //安装后,res.returnCode不等于PackageManager.INSTALL_SUCCEEDED时,清理残留文件
                    args.doPostInstall(res.returnCode, res.uid);
                }

                //如果a安装成功,b该安装操作不是更新,且c新软件包未选择退出备份,则应该执行还原。
                //update:false,doRestore:false
                final boolean update = res.removedInfo != null
                        && res.removedInfo.removedPackage != null;
                final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
                boolean doRestore = !update
                        && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
                .........
                .........
                //看名字,是正在运行的安装列表,put操作
                PostInstallData data = new PostInstallData(args, res);
                mRunningInstalls.put(token, data);
                //apk安装成功并且允许还原时,调用BackupManagerService服务备份
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
                    IBackupManager bm = IBackupManager.Stub.asInterface(
                            ServiceManager.getService(Context.BACKUP_SERVICE));
						.........
                        try {
                            // TODO: http://b/22388012
                            if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
                                bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
                            } else {
                                doRestore = false;
                            }
               			..........
                }
                if (!doRestore) {
                    //无需备份,发送POST_INSTALL消息执行安装完成后的工作
                    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);
                }
            }
        });
    }

installPackageTracedLI()方法将apk进行解析,然后进行dex到opt文件操作。最后发送POST_INSTALL消息。

                case POST_INSTALL: {
                    if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);

                    PostInstallData data = mRunningInstalls.get(msg.arg1);
                    final boolean didRestore = (msg.arg2 != 0);
                    //正在运行的安装列表,移除安装完成的
                    mRunningInstalls.delete(msg.arg1);

                    if (data != null) {
                        InstallArgs args = data.args;
                        PackageInstalledInfo parentRes = data.res;
						..........
                        // Handle the parent package
                        handlePackagePostInstall(parentRes, grantPermissions, killApp,
                                virtualPreload, grantedPermissions, didRestore,
                                args.installerPackageName, args.observer);

                        // Handle the child packages
                        final int childCount = (parentRes.addedChildPackages != null)
                                ? parentRes.addedChildPackages.size() : 0;
                        for (int i = 0; i < childCount; i++) {
                            PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
                            handlePackagePostInstall(childRes, grantPermissions, killApp,
                                    virtualPreload, grantedPermissions, false /*didRestore*/,
                                    args.installerPackageName, args.observer);
                        }
                        ..........
                } break;

这里主要看handlePackagePosetInstall()方法

private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
                                      boolean killApp, boolean virtualPreload, String[] grantedPermissions,
                                      boolean launchedForRestore, String installerPackage,
                                      IPackageInstallObserver2 installObserver) {
    if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
        // Send the removed broadcasts
        if (res.removedInfo != null) {
            res.removedInfo.sendPackageRemovedBroadcasts(killApp);
        }
        //已经安装成功,是否需要在发送广播之前赋予运行权限
        if (grantPermissions) {
            grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions);
        }
         .........
        // 如果程序包不是静态共享库,则发送已安装的广播。 
        if (res.pkg.staticSharedLibName == null) {
            mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
            //为新用户发送APK安装成功的消息
            int appId = UserHandle.getAppId(res.uid);
            boolean isSystem = res.pkg.applicationInfo.isSystemApp();
            sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
                    virtualPreload /*startReceiver*/, appId, firstUsers); 
            //为老用户发送APK安装成功的消息
            Bundle extras = new Bundle(1);
            extras.putInt(Intent.EXTRA_UID, res.uid);
            if (update) {
                extras.putBoolean(Intent.EXTRA_REPLACING, true);
            }
            sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                    extras, 0 /*flags*/,
                    null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);//发送APK安装成功的消息
          ......
        for (int userId : firstUsers) {
            PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId);
            //处理安装过程中可能的卸载操作导致包信息为null的异常
            if (info != null) {
                mDexManager.notifyPackageInstalled(info, userId);
            }
        }
    }
    //回调到PackageInstallerSession,告知apk安装完成
    if (installObserver != null) {
        try {
            Bundle extras = extrasForInstallResult(res);
            installObserver.onPackageInstalled(res.name, res.returnCode,
                    res.returnMsg, extras);
        } catch (RemoteException e) {
            Slog.i(TAG, "Observer no longer exists.");
        }
    }
}

至此,adb install 安装apk过程完成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
adb基本的命令教程 (1人评价)|347人阅读|9次下载|举报文档 手?机?A?D?B?命?令 要使用adb命令,手机需要打开USB debug 安装软件 adb install apk文件名称.apk 重新安装该软件 adb install -r apk文件名称.apk 卸载apk软件 adb uninstall apk包名.apk 查看手机上的运行日志,此项可以用来查错 adb logcat 查看手机是否连接,以及连接了几台手机 adb devices A为手机路径,B为电脑路径,意思为:把文件从手机中复制到电脑上 adb pull A为手机路径,B为电脑路径,意思为:把文件从电脑复制到手机上 adb push 进入手机的超级终端Termil adb shell 重新挂载文件系统 adb remount 重启手机 adb reboot 重启到Recovery界面 adb reboot recovery 重启到bootloader界面 adb reboot bootloader 例子:刷官方高版本后重新获取ROOT和降级方法(部份操作) 进行adb运行环境 adb shell 设置超级用户模式 su 映射出目录 mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system 退出su exit 退出shell准备接受下一个adb命令 exit 增加flash_image文件到手机上 adb push flash_image.zip /system/bin/flash_image recovery先复制到卡上 adb push recovery-RA-heroc-v1.6.2.img /sdcard B?? 再次进入adb环境 adb shell 修改文件属性 chmod 0755 /system /bin/flash_image 重启系统 reboot 1234567890ABCDEFGHIJKLMNabcdefghijklmn!@#$%^&&*()_+.一三五七九贰肆陆扒拾,。青玉案元夕东风夜放花千树更吹落星如雨宝马雕车香满路凤箫声动玉壶光转一夜鱼龙舞蛾儿雪柳黄金缕笑语盈盈暗香去众里寻他千百度暮然回首那人却在灯火阑珊处

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值