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);
- }
-
- }
- 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