adb install 也是用的pm命令去安装的,所以开始是在pm.java中。
frameworks\base\services\java\com\android\server\pm
1、调用pm程序开始安装
得用Pm安装时,一般是shell运行一个pm命令,并传送相应的参数,我们通过adb连接到机器,输入pm,会打出pm的一些参数
# pm
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); } }跟踪scanPackageLI()方法后发现,程序经过很多次的if else 的筛选,最后判定可以安装后调用了 mInstaller.installprivate void installNewPackageLI(PackageParser.Package pkg, int parseFlags,int scanMode, String installerPackageName, PackageInstalledInfo res) { ***********************省略若干************************************************* PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode, System.currentTimeMillis()); ***********************省略若干************************************************** }
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