APK安装原理

2019-12-30  本文已影响0人  瑜小贤

基于android 5.0

PackageInstallerActivity.java

InstallAppProgress.java

int adb_commandline(int argc, char** argv){
  //...
  if(!strcmp(argv[0], "install")){
    if(argc < 2) return usage();
    //调用install_app函数进行处理
    return install_app(ttype, serial, argc, argv);
  }
}

int install_app(transport_type transport, char* serial, int argc, char** argv){
  static const char *const DATA_DEST = "/data/local/tmp/%s";
  static const char *const SD_DEST = "/sdcard/tmp/%s"
  const char* where = DATA_DEST;
  //...
  int err = do_sync_push(apk_file, apk_dest, 0 /*no show progress*/);//将apk push到目标目录 进行解析安装
  //...
  pm_command(transport, serial, argc, argv);
  //...
}

static int pm_command(transport_type transport, char* serial, int argc, char** argv){
  char buf[4096];

  snpintf(buf, sizeof(buf), "shell:pm"); //指向一个pm脚本文件

  //...
  send_shellcommand(transport, serial, buf);
  return 0;
}


frameworks/base/cmds/pm/pm

base=/system
export CLASSPATH=$base/framework/pm.jar
exec app_process $base/bin com.android.commands.pm.P "$@"

frameworks/base/cmds/pm 下的工程源码,生成了上文的pm.jar,而工程源码中的唯一java文件是 Pm.java

public final class Pm{
  //...
  IPackageManager mPm;
  IPackageInstaller mInstaller;
  IUserManager mUm;
  //...
  public static void main(String[] args){
    int exitCode = 1;
    try{
      exitCode = new Pm().run(args);
    } catch(Exception e){
      Log.e(TAG, "Error", e);
      System.err.println("Error:" + e);
      if(e instanceof RemoteException){
        System.err.println(PM_NOT_RUNING_ERR);
      }
    }
    System.exit(exitCode);
  }

  public int run(String[] args) throws IOException, RemoteException{
    //...
    mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    //...
    if("install".equals(op)){
      return runInstall();
    }
    //...
  }

  private int runInstall(){
    //...
    try{
      VerificationParams verificationParams = new VerificationParams(verificationURI,
          originatingURI, referrerURI, VerificationParams.NO_UID, null);
      mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, 
          installerPackageName, verificationParams, abi, userId); //从Pm.java到PackageManagerService中
      //...
    }catch(RemoteException e){
     //...
    }
    //...
  }
  //...
}

PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub{
  //...
  /**
   * bind机制服务端
   *
   * @param originPath 要安装apk的路径
   * @param observer 监听apk安装的结果信息
   * @param installFlags 安装的相关参数
   * @param installerPackageName 安装的包名
   * @param userId userId
  **/
  @Override 
  public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
      int installFlags, String installerPackageName, int userId){
    //...
    //组装消息,发送handler
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    //...
    mHandler.sendMessage(msg);
  }

  class PackageHandler extends Handler {
    //...
    void doHandleMessage(Message msg){
      switch(msg.what){
        case INIT_COPY:{
          //...
          mHadnler.sendEmptyMessage(MCS_BOUND);
          //...
          break;
        }
    
        case MCS_BOUND:{
          //...
          if(params.startCopy()){
            //...
          }
          //...
          break;
        }
      }
    }

  private abstract class HandlerParams {
    private static final int MAX_RETRIES = 4;
    //...
    final boolean startCopy(){
      boolean res;
      try{
        if(++mRetries > MAX_RETRIES){ //默认尝试安装4次
          mHandler.sendEmptyMessage(MCS_GIVE_UP);
          handleServiceError();
          return false;
        }else{
          handleStartCopy();
          res = true;
        }
      }catch(RemoteException e){
        mHandler.sendEmptyMessage(MCS_RECONNECT);
        res = false;
      }
      handleReturnCode();
      return res;
    }
    //...
    abstract void handleReturnCode();
  }
  //...
}
无界面安装 Apk安装的原理
上一篇下一篇

猜你喜欢

热点阅读