当前位置:   article > 正文

adb install 深入分析

adb ins

adb install 也是用的pm命令去安装的,所以开始是在pm.java中。

frameworks\base\services\java\com\android\server\pm 

1、调用pm程序开始安装

得用Pm安装时,一般是shell运行一个pm命令,并传送相应的参数,我们通过adb连接到机器,输入pm,会打出pm的一些参数

# pm
pm

frameworks\base\cmds\pm\src\com\android\commands\pm    
  1. public static void main(String[] args) {
  2. new Pm().run(args);
  3. }
  1. public void run(String[] args) {
  2. ......进行一系列的判断......
  3. if ("install".equals(op)) {
  4. runInstall();
  5. return;
  6. }
  7. }
  1. private void runInstall() {
  2. ................此处省略一万字......................
  3. mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
  4. verificationURI, null);
  5. }

   frameworks\base\services\java\com\android\server\pm

  1. public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
  2. int flags, String installerPackageName, Uri verificationURI,
  3. ManifestDigest manifestDigest) {
  4. .................此处省略一万字.............................
  5. final Message msg = mHandler.obtainMessage(INIT_COPY);
  6. msg.obj = new InstallParams(packageURI, observer,filteredFlags,installerPackageName,
  7. verificationURI, manifestDigest);
  8. mHandler.sendMessage(msg);
  9. }
  1. void doHandleMessage(Message msg) {
  2. switch (msg.what) {
  3. case INIT_COPY: {
  4. if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
  5. HandlerParams params = (HandlerParams) msg.obj;
  6. int idx = mPendingInstalls.size();
  7. if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
  8. // If a bind was already initiated we dont really
  9. // need to do anything. The pending install
  10. // will be processed later on.
  11. if (!mBound) {
  12. // If this is the only one pending we might
  13. // have to bind to the service again.
  14. //连接服务 链接上返回真走else
  15. if (!connectToService()) {
  16. Slog.e(TAG, "Failed to bind to media container service");
  17. params.serviceError();
  18. return;
  19. } else {
  20. // Once we bind to the service, the first
  21. // pending request will be processed.
  22. mPendingInstalls.add(idx, params);
  23. }
  24. } else {
  25. mPendingInstalls.add(idx, params);
  26. // Already bound to the service. Just make
  27. // sure we trigger off processing the first request.
  28. if (idx == 0) {
  29. mHandler.sendEmptyMessage(MCS_BOUND);
  30. }
  31. }
  32. break;
  33. }


调用connectToService方法
  1. private boolean connectToService() {
  2. if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
  3. " DefaultContainerService");
  4. //连接服务DefaultContainerService
  5. Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
  6. //设置线程默认应用的优先级
  7. Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
  8. //在连接成功的时候触发DefaultContainerConnection的onServiceConnected
  9. if (mContext.bindService(service, mDefContainerConn,
  10. Context.BIND_AUTO_CREATE)) {
  11. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  12. mBound = true;
  13. return true;
  14. }
  15. //设置线程优先级为后台,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理
  16. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  17. return false;
  18. }

连接服务DefaultContainerConnection 绑定成功发送一条消息MCS_BOUND

  1. final private DefaultContainerConnection mDefContainerConn =
  2. new DefaultContainerConnection();
  3. class DefaultContainerConnection implements ServiceConnection {
  4. public void onServiceConnected(ComponentName name, IBinder service) {
  5. if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
  6. IMediaContainerService imcs =
  7. IMediaContainerService.Stub.asInterface(service);
  8. //PackageHandler发了一条MCS_BOUND
  9. mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
  10. }
  11. public void onServiceDisconnected(ComponentName name) {
  12. if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
  13. }
  14. };


 发送了一条消息MCS_BOUND和 IMediaContainerService imcs 对象
IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);

 调用方法params.startCopy()

 

  1. final boolean startCopy() {
  2. boolean res;
  3. try {
  4. if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
  5. if (++mRetries > MAX_RETRIES) {
  6. Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
  7. mHandler.sendEmptyMessage(MCS_GIVE_UP);
  8. handleServiceError();
  9. return false;
  10. } else {
  11. //安装前的准备工作
  12. handleStartCopy();
  13. res = true;
  14. }
  15. } catch (RemoteException e) {
  16. if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
  17. mHandler.sendEmptyMessage(MCS_RECONNECT);
  18. res = false;
  19. }
  20. handleReturnCode();
  21. return res;
  22. }

 handleStartCopy进行一些安装前准备工作,最后调用handleReturnCode

  1. void handleReturnCode() {
  2. // If mArgs is null, then MCS couldn't be reached. When it
  3. // reconnects, it will try again to install. At that point, this
  4. // will succeed.
  5. if (mArgs != null) {
  6. processPendingInstall(mArgs, mRet);
  7. }
  8. }

mArgs 在handleStartCopy进行了初始化

 

  1. /*
  2. * 调用远程方法来获取和安装包信息
  3. * Invoke remote method to get package information and install
  4. * location values. Override install location based on default
  5. * policy if needed and then create install arguments based
  6. * on the install location.
  7. */
  8. public void handleStartCopy() throws RemoteException {
  9. ..............................
  10. int ret = PackageManager.INSTALL_SUCCEEDED;
  11. final InstallArgs args = createInstallArgs(this);
  12. mArgs = args;
  13. }
  1. private void processPendingInstall(final InstallArgs args, final int currentStatus) {
  2. // Queue up an async operation since the package installation may take a little while.
  3. mHandler.post(new Runnable() {
  4. public void run() {
  5. mHandler.removeCallbacks(this);
  6. // Result object to be returned
  7. PackageInstalledInfo res = new PackageInstalledInfo();
  8. res.returnCode = currentStatus;
  9. res.uid = -1;
  10. res.pkg = null;
  11. res.removedInfo = new PackageRemovedInfo();
  12. if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
  13. args.doPreInstall(res.returnCode);
  14. synchronized (mInstallLock) {
  15. installPackageLI(args, true, res);
  16. }
  17. args.doPostInstall(res.returnCode);
  18. }
installPackageLI调用这个方法

在installPackageLI中,会new 一个PackageParser对package进行解析,调用parsePackage函数 parsePackage(File sourceFile, String destCodePath,
            DisplayMetrics metrics, int flags)函数根据参数进行一些处理后最终调用parsePackage(
        Resources res, XmlResourceParser parser, int flags, String[] outError)对包进行解析,我们看到这个函数里面主要对配置文件AndroidManifest.xml文件进行了解析。

  1. //这个函数里面主要对配置文件AndroidManifest.xml文件进行了解析
  2. //返回解析到的所有数据pkg
  3. final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
  4. null, mMetrics, parseFlags);
  1. private void installPackageLI(InstallArgs args,
  2. boolean newInstall, PackageInstalledInfo res) {
  3. ..............................
  4. //replace判断设备上面是否有安装的app
  5. if (replace) {
  6. replacePackageLI(pkg, parseFlags, scanMode,
  7. installerPackageName, res);
  8. } else {
  9. installNewPackageLI(pkg, parseFlags, scanMode,
  10. installerPackageName,res);
  11. }
  12. }
  1. private void installNewPackageLI(PackageParser.Package pkg,
  2. int parseFlags,int scanMode,
  3. String installerPackageName, PackageInstalledInfo res) {
  4. ***********************省略若干*************************************************
  5. PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
  6. System.currentTimeMillis());
  7. ***********************省略若干**************************************************
  8. }
跟踪scanPackageLI()方法后发现,程序经过很多次的if else 的筛选,最后判定可以安装后调用了 mInstaller.install
  1. if (mInstaller != null) {
  2. int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,pkg.applicationInfo.uid);
  3. if(ret < 0) {
  4. // Error from installer
  5. mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
  6. return null;
  7. }
  8. }

 技术交流群  182189263

转载于:https://my.oschina.net/u/861587/blog/118687

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/199146
推荐阅读
相关标签
  

闽ICP备14008679号