adb install 深入分析

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    
public static void main(String[] args) {
        new Pm().run(args);
    }
public void run(String[] args) {
......进行一系列的判断......
       if ("install".equals(op)) {
            runInstall();
            return;
        }
}
private void runInstall() {

................此处省略一万字......................
 mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
                    verificationURI, null);
}

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

public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
            int flags, String installerPackageName, Uri verificationURI,
            ManifestDigest manifestDigest) {

.................此处省略一万字.............................
   final Message msg = mHandler.obtainMessage(INIT_COPY);
   msg.obj = new InstallParams(packageURI, observer,filteredFlags,installerPackageName,
                verificationURI, manifestDigest);
        mHandler.sendMessage(msg);
}
void doHandleMessage(Message msg) {
            switch (msg.what) {
                case INIT_COPY: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
                    // If a bind was already initiated we dont really
                    // need to do anything. The pending install
                    // will be processed later on.
                    if (!mBound) {
                        // If this is the only one pending we might
                        // have to bind to the service again.
						//连接服务 链接上返回真走else
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            params.serviceError();
                            return;
                        } else {
                            // Once we bind to the service, the first
                            // pending request will be processed.
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                        mPendingInstalls.add(idx, params);
                        // Already bound to the service. Just make
                        // sure we trigger off processing the first request.
                        if (idx == 0) {
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }


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

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

final private DefaultContainerConnection mDefContainerConn =
            new DefaultContainerConnection();
    class DefaultContainerConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
            IMediaContainerService imcs =
                IMediaContainerService.Stub.asInterface(service);
				//PackageHandler发了一条MCS_BOUND
            mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
        }

        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
        }
    };


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

 调用方法params.startCopy()

 

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

                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进行一些安装前准备工作,最后调用handleReturnCode

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

mArgs 在handleStartCopy进行了初始化

 

/*
         * 调用远程方法来获取和安装包信息
          * Invoke remote method to get package information and install
         * location values. Override install location based on default
         * policy if needed and then create install arguments based
         * on the install location.
         */
        public void handleStartCopy() throws RemoteException {
  
             ..............................
            int ret = PackageManager.INSTALL_SUCCEEDED;
            final InstallArgs args = createInstallArgs(this);
            mArgs = args;

       }
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        // Queue up an async operation since the package installation may take a little while.
		
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                 // Result object to be returned
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.returnCode = currentStatus;
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = new PackageRemovedInfo();
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                        installPackageLI(args, true, res);
                    }
                    args.doPostInstall(res.returnCode);
                }
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文件进行了解析。

//这个函数里面主要对配置文件AndroidManifest.xml文件进行了解析
		//返回解析到的所有数据pkg
        final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
                null, mMetrics, parseFlags);
private void installPackageLI(InstallArgs args,
            boolean newInstall, PackageInstalledInfo res) {

          ..............................
        //replace判断设备上面是否有安装的app
        if (replace) {
            replacePackageLI(pkg, parseFlags, scanMode,
                    installerPackageName, res);
        } else {
            installNewPackageLI(pkg, parseFlags, scanMode,
                    installerPackageName,res);
        }

}
private void installNewPackageLI(PackageParser.Package pkg,  
            int parseFlags,int scanMode,  
            String installerPackageName, PackageInstalledInfo res) {  
     ***********************省略若干*************************************************  
        PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,  
               System.currentTimeMillis());  
     ***********************省略若干**************************************************    
} 
跟踪scanPackageLI()方法后发现,程序经过很多次的if else 的筛选,最后判定可以安装后调用了 mInstaller.install
if (mInstaller != null) {  
    int ret = mInstaller.install(pkgName, useEncryptedFSDir,  pkg.applicationInfo.uid,pkg.applicationInfo.uid);  
    if(ret < 0) {  
         // Error from installer  
       mLastScanError =    PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;  
                        return null;  
                    }  
                }

 技术交流群  182189263

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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!@#$%^&&*()_+.一三五七九贰肆陆扒拾,。青玉案元夕东风夜放花千树更吹落星如雨宝马雕车香满路凤箫声动玉壶光转一夜鱼龙舞蛾儿雪柳黄金缕笑语盈盈暗香去众里寻他千百度暮然回首那人却在灯火阑珊处

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值