Android-Apk的安装流程分析(二)

Android-Apk的安装流程分析(一)

接着上节的内容来说,之前说到了PackageInstallerSession中调用PackageManaPgerService(简称PMS)的installStage这个方法来完成后续的安装流程

下面的流程基本的都是在PMS中进行的,我们来看下流程

1、PackageManaPgerService#installStage
void installStage(String packageName, File stagedDir, String stagedCid,
            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
            String installerPackageName, int installerUid, UserHandle user,
            Certificate[][] certificates) {
        if (DEBUG_EPHEMERAL) {
            if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
                Slog.d(TAG, "Ephemeral install of " + packageName);
            }
        }
        final VerificationInfo verificationInfo = new VerificationInfo(
                sessionParams.originatingUri, sessionParams.referrerUri,
                sessionParams.originatingUid, installerUid);

        final OriginInfo origin;
        if (stagedDir != null) {
            origin = OriginInfo.fromStagedFile(stagedDir);
        } else {
            origin = OriginInfo.fromStagedContainer(stagedCid);
        }
		
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        //实例化一个安装参数,里面有传进来的安装信息
        final InstallParams params = new InstallParams(origin, null, observer,
                sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                verificationInfo, user, sessionParams.abiOverride,
                sessionParams.grantedRuntimePermissions, certificates);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;

        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
                System.identityHashCode(msg.obj));
        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                System.identityHashCode(msg.obj));
		//发送一个INIT_COPY 的message
        mHandler.sendMessage(msg);
    }

这个方法就干了一个事情,发送了一个首次copy的消息,然后处理,看看这个handler怎么处理的

2、PackageManaPgerService#doHandleMessage
 void doHandleMessage(Message msg) {
            switch (msg.what) {
            //这个就是发来的消息
                case INIT_COPY: {
                    HandlerParams params = (HandlerParams) msg.obj;
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    // If a bind was already initiated we dont really
                    // need to do anything. The pending install
                    // will be processed later on.
                    //启动pms的时候 mContainerService 服务已经被绑定了
                    if (!mBound) {
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        // If this is the only one pending we might
                        // have to bind to the service again.
                        // 尝试绑定服务,这里就是bindService
                        if (!connectToService()) {
                            Slog.e(TAG, "Failed to bind to media container service");
                            params.serviceError();
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                    System.identityHashCode(mHandler));
                            if (params.traceMethod != null) {
                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
                                        params.traceCookie);
                            }
                            return;
                        } else {
                            // Once we bind to the service, the first
                            // pending request will be processed.
                            //绑定成功就添加一个待copy的apk 数据 等待copy
                            //每次连接成功都会发送一个MCS_BOUND 消息 然后处理copy任务,
                            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) {
                            //触发下面的MCS_BOUND,进行拷贝apk,然后就是不断循环,消耗
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }
                case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                        mContainerService = (IMediaContainerService) msg.obj;
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                    }
                    if (mContainerService == null) {
                        if (!mBound) {
                            // Something seriously wrong since we are not bound and we are not
                            // waiting for connection. Bail out.
                            Slog.e(TAG, "Cannot bind to media container service");
                            for (HandlerParams params : mPendingInstalls) {
                                // Indicate service bind error
                                params.serviceError();
                                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                        System.identityHashCode(params));
                                if (params.traceMethod != null) {
                                    Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
                                            params.traceMethod, params.traceCookie);
                                }
                                return;
                            }
                            mPendingInstalls.clear();
                        } else {
                            Slog.w(TAG, "Waiting to connect to media container service");
                        }
                    } else if (mPendingInstalls.size() > 0) {
                        HandlerParams params = mPendingInstalls.get(0);
                        if (params != null) {
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                    System.identityHashCode(params));
                            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                             //开始拷贝
                            if (params.startCopy()) {
                                // We are done...  look for more work or to
                                // go idle.
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Checking for more work or unbind...");
                                // Delete pending install
                                if (mPendingInstalls.size() > 0) {
                                    //拷贝成功了就移除拷贝任务数据
                                    mPendingInstalls.remove(0);
                                }
                                if (mPendingInstalls.size() == 0) {
                                    if (mBound) {
                                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                                "Posting delayed MCS_UNBIND");
                                        removeMessages(MCS_UNBIND);
                                        Message ubmsg = obtainMessage(MCS_UNBIND);
                                        // Unbind after a little delay, to avoid
                                        // continual thrashing.
                                        //数据没有了 等待10s 就断开服务
                                        sendMessageDelayed(ubmsg, 10000);
                                    }
                                } else {
                                    // There are more pending requests in queue.
                                    // Just post MCS_BOUND message to trigger processing
                                    // of next pending install.
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting MCS_BOUND for next work");
                                    //如果数据还有就继续执行下一个copy
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                        }
                    } else {
                        // Should never happen ideally.
                        Slog.w(TAG, "Empty queue");
                    }
                    break;
                }
                x
                x
                x
                x
                x
                x
                x 省略代码,,,

总结:

目的:把apk从PackageInstallerSession的暂存目录中 复制到data/app/ 目录下面 或则sdcard的目录下面,这个根据安装参数的flag来区分,为后续工作做准备

过程

1、这个复制的过程是交给DefaultContainerService 这个服务去做的,这个服务在单独的进程

2、每次需要复制的时候先连接服务

private boolean connectToService() {
            if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
                    " DefaultContainerService");
            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
            //可以看到是通过bind方式的
            if (mContext.bindServiceAsUser(service, mDefContainerConn,
                    Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                mBound = true;
                return true;
            }
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            return false;
        }

3、然后启动了这个服务,在这个同时做了这个操作 mPendingInstalls.add(idx, params); 还有发送了一个MCS_BOUND消息给handler执行拷贝,这个消息是绑定服务成功后做的事情

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);
                //可以看到绑定成功发送了一个MCS_BOUND消息,可以完成后续的拷贝工作
            mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
        }

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

4、MCS_BOUND 的指令下 最后调用了HandlerParams的startCopy方法,HandlerParams是一个抽象类,这里用的实现类是InstallParams ,这里多说一句HandlerParams的实现类有2种MeasureParams,和InstallParams ,

MeasureParams 是测量的作用,计算apk所占用的空间大小

InstallParams 是安装apk的拷贝作用,处理拷贝的任务

HandlerParams的startCopy方法最终会依次调用到handleStartCopy() 还有handleReturnCode() 两个方法

handleStartCopy处理拷贝,需要子类实现

handleReturnCode 处理返回结果,引发后续流程,需要子类实现

5、InstallParams 的handleStartCopy

  ......省略......
  } else {
                    /*
                     * No package verification is enabled, so immediately start
                     * the remote call to initiate copy using temporary file.
                     */
                    ret = args.copyApk(mContainerService, true);
                }

我们看到这个arsg 其实是

final InstallArgs args = createInstallArgs(this);

createInstallArgs方法是

 private InstallArgs createInstallArgs(InstallParams params) {
        if (params.move != null) {
            return new MoveInstallArgs(params);
        } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
            return new AsecInstallArgs(params);
        } else {
            return new FileInstallArgs(params);
        }
    }

这里有三个实现类,

MoveInstallArgs :是处理已经安装了的apk的数据转移的

AsecInstallArgs:这个是处理asec 就是在sdcard安装apk的拷贝类型

FileInstallArgs:这个就是系统内存储的,拷贝到data/app/ 下的类型

我们就来看下FileInstallArgs类型的copyApk

最终 调用了doCopyApk,

private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
            if (origin.staged) {
                if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
                codeFile = origin.file;
                resourceFile = origin.file;
                return PackageManager.INSTALL_SUCCEEDED;
            }

            try {
                final boolean isEphemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
                //从PackageInstallerService 获取目录,这个最终是在Environment中设置好的
                final File tempDir =
                        mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
                codeFile = tempDir;
                resourceFile = tempDir;
            } catch (IOException e) {
                Slog.w(TAG, "Failed to create copy file: " + e);
                return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
            }
			//这个是跨进程 实现文件流的读写作用的类,下面很明显是根据文件名称,然后实例化一个文件描述符,最终转为Out流,进行读写
            final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
                @Override
                public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
                    if (!FileUtils.isValidExtFilename(name)) {
                        throw new IllegalArgumentException("Invalid filename: " + name);
                    }
                    try {
                        final File file = new File(codeFile, name);
                        final FileDescriptor fd = Os.open(file.getAbsolutePath(),
                                O_RDWR | O_CREAT, 0644);
                        Os.chmod(file.getAbsolutePath(), 0644);
                        return new ParcelFileDescriptor(fd);
                    } catch (ErrnoException e) {
                        throw new RemoteException("Failed to open: " + e.getMessage());
                    }
                }
            };

            int ret = PackageManager.INSTALL_SUCCEEDED;
            //最终调用了DefaultContainerService 的 copyPackage方法
            ret = imcs.copyPackage(.getAbsolutePaorigin.fileth(), target);
            if (ret != PackageManager.INSTALL_SUCCEEDED) {
                Slog.e(TAG, "Failed to copy package");
                return ret;
            }
			//下面是so库的拷贝
            final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
            NativeLibraryHelper.Handle handle = null;
            try {
                handle = NativeLibraryHelper.Handle.create(codeFile);
                ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                        abiOverride);
            } catch (IOException e) {
                Slog.e(TAG, "Copying native libraries failed", e);
                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
            } finally {
                IoUtils.closeQuietly(handle);
            }

            return ret;
        }

最后在看下DafaultContainerService的拷贝实现

 @Override
        public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {
            if (packagePath == null || target == null) {
                return PackageManager.INSTALL_FAILED_INVALID_URI;
            }
			//这个是轻量化的apk包,这个包有可能是一个apk文件是全量的,有可能是一个apk的目录,李米娜有很多的子apk。还有其他文件,这种情况是因为方法数65535超过后,google做的把apk拆分的策略
            PackageLite pkg = null;
            try {
                final File packageFile = new File(packagePath);
                pkg = PackageParser.parsePackageLite(packageFile, 0);
                return copyPackageInner(pkg, target);
            } catch (PackageParserException | IOException | RemoteException e) {
                Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
                return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
            }
        }

下面是后续实现

 private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
            throws IOException, RemoteException {
        copyFile(pkg.baseCodePath, target, "base.apk");
        if (!ArrayUtils.isEmpty(pkg.splitNames)) {
        //看到如果是多个apk就是splitNames 数组 多个了,以此都要拷贝
            for (int i = 0; i < pkg.splitNames.length; i++) {
                copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
            }
        }
		//拷贝完成就返回成功
        return PackageManager.INSTALL_SUCCEEDED;
    }

    private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
            throws IOException, RemoteException {
        Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(sourcePath);
            out = new ParcelFileDescriptor.AutoCloseOutputStream(
            //这里这个open 就是前面的 open 传过来的的ParcelFileDescriptor
                    target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
                    //最终的复制工作,拷贝完成
            Streams.copy(in, out);
        } finally {
            IoUtils.closeQuietly(out);
            IoUtils.closeQuietly(in);
        }
    }

6、InstallParams#handleReturnCode

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

这个方法是执行完成了拷贝apk任务后返回的结果

最终调用了PMS的processPendingInstall方法

3、PackageManaPgerService#processPendingInstall
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.setReturnCode(currentStatus);
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = null;
               
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                 //如果安装成功 执行doPreInstall 主要是解析apk前的清理工作
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                    //核心方法 
                        installPackageTracedLI(args, res);
                    }
                    //后续操作,如果没安装成功 就做清理工作
                    args.doPostInstall(res.returnCode, res.uid);
                }

                // A restore should be performed at this point if (a) the install
                // succeeded, (b) the operation is not an update, and (c) the new
                // package has not opted out of backup participation.
                final boolean update = res.removedInfo != null
                        && res.removedInfo.removedPackage != null;
                final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
                boolean doRestore = !update
                        && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);

                // Set up the post-install work request bookkeeping.  This will be used
                // and cleaned up by the post-install event handling regardless of whether
                // there's a restore pass performed.  Token values are >= 1.
                int token;
                if (mNextInstallToken < 0) mNextInstallToken = 1;
                token = mNextInstallToken++;

                PostInstallData data = new PostInstallData(args, res);
                mRunningInstalls.put(token, data);
                if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
				//如果apk 程序设置了备份 就执行备份操作
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
                    // Pass responsibility to the Backup Manager.  It will perform a
                    // restore if appropriate, then pass responsibility back to the
                    // Package Manager to run the post-install observer callbacks
                    // and broadcasts.
                    IBackupManager bm = IBackupManager.Stub.asInterface(
                            ServiceManager.getService(Context.BACKUP_SERVICE));
                    if (bm != null) {
                        if (DEBUG_INSTALL) Log.v(TAG, "token " + token
                                + " to BM for possible restore");
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
                        try {
                            // TODO: http://b/22388012
                            if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
                                bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
                            } else {
                                doRestore = false;
                            }
                        } catch (RemoteException e) {
                            // can't happen; the backup manager is local
                        } catch (Exception e) {
                            Slog.e(TAG, "Exception trying to enqueue restore", e);
                            doRestore = false;
                        }
                    } else {
                        Slog.e(TAG, "Backup Manager not found!");
                        doRestore = false;
                    }
                }

                if (!doRestore) {
                    // No restore possible, or the Backup Manager was mysteriously not
                    // available -- just fire the post-install work request directly.
                    if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
					//发送消息给上层 安装完成,整个安装执行完毕
                    Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                    mHandler.sendMessage(msg);
                }
            }
        });
    }

我们继续看installPackageTracedLI

4、PackageManaPgerService#installPackageTracedLI
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
            installPackageLI(args, res);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }
5、PackageManaPgerService#installPackageLI
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
    ...
    // 1. 解析package信息,
    final PackageParser.Package pkg;
    try {
        pkg = pp.parsePackage(tmpPackageFile, parseFlags);
    } catch (PackageParserException e) {
        res.setError("Failed parse during installPackageLI", e);
        return;
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
    // 2. 签名校验
    try {
        verifySignaturesLP(signatureCheckPs, pkg);
    } catch (PackageManagerException e) {
        res.setError(e.error, e.getMessage());
        return;
    }
    // 3. 对dex进行优化
    mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                                       null , false ,
                                       getCompilerFilterForReason(REASON_INSTALL),
                                       getOrCreateCompilerPackageStats(pkg),
                                       mDexManager.isUsedByOtherApps(pkg.packageName));
    // 4. 重命名 将文件夹的名称重命名为 “包名”,就是data/app/com.xx.xx/ 这样
    if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
        res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
        return;
    }
    // 5. 替换或新安装APK,走不同的路线
    if (replace) {
    	replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
                installerPackageName, res, args.installReason); 
    } else {
    	installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
            args.user, installerPackageName, volumeUuid, res, args.installReason); 
	}
}

上面的这个方法很长,我做了重点提取 以及注释

我们看下最后的installNewPackageLIF 安装一个新的apk文件

6、PackageManaPgerService#installNewPackageLIF
  /*
     * Install a non-existing package.
     */
    private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
            PackageInstalledInfo res) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");

        // Remember this for later, in case we need to rollback this install
        String pkgName = pkg.packageName;

        if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);

        synchronized(mPackages) {
            if (mSettings.mRenamedPackages.containsKey(pkgName)) {
                // A package with the same name is already installed, though
                // it has been renamed to an older name.  The package we
                // are trying to install should be installed as an update to
                // the existing one, but that has not been requested, so bail.
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling package running as "
                        + mSettings.mRenamedPackages.get(pkgName));
                return;
            }
            if (mPackages.containsKey(pkgName)) {
                // Don't allow installation over an existing package with the same name.
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling.");
                return;
            }
        }

        try {
            //扫描这个apk
            PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                    System.currentTimeMillis(), user);
			//将扫描的结果 更新到setting中
            updateSettingsLI(newPackage, installerPackageName, null, res, user);

            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                prepareAppDataAfterInstallLIF(newPackage);

            } else {
                // Remove package from internal structures, but keep around any
                // data that might have already existed
                //如果失败了就删除 中间的临时文件
                deletePackageLIF(pkgName, UserHandle.ALL, false, null,
                        PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
            }
        } catch (PackageManagerException e) {
            res.setError("Package couldn't be installed in " + pkg.codePath, e);
        }

        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
7、PackageManaPgerService#scanPackageTracedLI
  private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
        try {
            return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }
8、PackageManaPgerService#scanPackageLI
    private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
            long currentTime, UserHandle user) throws PackageManagerException {
        if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
        PackageParser pp = new PackageParser();
        pp.setSeparateProcesses(mSeparateProcesses);
        pp.setOnlyCoreApps(mOnlyCore);
        pp.setDisplayMetrics(mMetrics);

        if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
            parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
        }

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
        final PackageParser.Package pkg;
        try {
            pkg = pp.parsePackage(scanFile, parseFlags);
        } catch (PackageParserException e) {
            throw PackageManagerException.from(e);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }

        return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
    }
9、PackageManaPgerService#scanPackageLI
 /**
     *  Scans a package and returns the newly parsed package.
     *  @throws PackageManagerException on a parse error.
     */
    private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
            throws PackageManagerException {
        // If the package has children and this is the first dive in the function
        // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
        // packages (parent and children) would be successfully scanned before the
        // actual scan since scanning mutates internal state and we want to atomically
        // install the package and its children.
        if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
            if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
                scanFlags |= SCAN_CHECK_ONLY;
            }
        } else {
            scanFlags &= ~SCAN_CHECK_ONLY;
        }

        // Scan the parent
        PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
                scanFlags, currentTime, user);

        // Scan the children
        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
        for (int i = 0; i < childCount; i++) {
            PackageParser.Package childPackage = pkg.childPackages.get(i);
            scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
                    currentTime, user);
        }


        if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
            return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
        }

        return scannedPkg;
    }
10、PackageManaPgerService#scanPackageLI
 private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        boolean success = false;
        try {
            final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
                    currentTime, user);
            success = true;
            return res;
        } finally {
            if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                // DELETE_DATA_ON_FAILURES is only used by frozen paths
                destroyAppDataLIF(pkg, UserHandle.USER_ALL,
                        StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
            }
        }
    }

上面这些scanPackageLI 都是同名的方法,但是参数不同,

11、PackageManaPgerService#scanPackageDirtyLI

这个方法是很长的核心方法

主要功能:

对扫描的package 进行解析,然后把四大组件还有权限的信息 添加到PMS的内部数据集合中保存起来,供系统中的其他app或者服务来访问,PMS在系统中的作用相当于是系统的app数据中心,存储了app的一切信息,

scanPackageDirtyLI
{

// 针对包名为"android" 的APK进行处理, 这个app 主要是
//选择是ChoseActivity 就是有相同的Intent 弹出的界面
//还有个关机app的界面
 if (pkg.packageName.equals("android")) {
//shouldCheckUpgradeKeySetLP方法进行密钥检查,是否一致
if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags))
// 重新验证签名
verifySignaturesLP(pkgSetting, pkg);
// 确定 进程的名称
pkg.applicationInfo.processName = fixProcessName(
                pkg.applicationInfo.packageName,
                pkg.applicationInfo.processName,
                pkg.applicationInfo.uid);
// 设置native相关属性 系统app native 会统一放在/system/lib/
//如果是普通app 在/data/data/packageName/lib下建立和CPU类型对应的目录,例如ARM平台 arm,MIP平台 mips/
//设置native 库的路径
// 创建native库链接
//注册pkg里面的provider到PMS上的mProvider上
// 注册该Package中的service到PMS的mServices上
// 注册pkg里面的receiver到PMS上的receivers上
//注册pkg里面的activity到PMS上的activities上
//注册pkg里面的PermissionGroup到PMS上的mPermissionGroups上
//注册pkg里面的Permission到PMS上的permissionMap上
//注册pkg里面的instrumentation到PMS的mInstrumentation中

经历了上面的过程在PMS的安装过程已经完成了,接下来就是通知上层创建成功了

12、PackageManagerService#handlePackagePostInstall

安装完成后,后续流程会发送一个POST_INSTALL消息给mHandler 然后执行handlePackagePostInstall方法

 。。。。。。。省略。。。。。。
 // If someone is watching installs - notify them
        if (installObserver != null) {
            try {
                Bundle extras = extrasForInstallResult(res);
                //回调通知上层
                installObserver.onPackageInstalled(res.name, res.returnCode,
                        res.returnMsg, extras);
            } catch (RemoteException e) {
                Slog.i(TAG, "Observer no longer exists.");
            }
        }
13、PackageInstallerSession#dispatchSessionFinished
 final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
            @Override
            public void onUserActionRequired(Intent intent) {
                throw new IllegalStateException();
            }

            @Override
            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                    Bundle extras) {
                destroyInternal();
                dispatchSessionFinished(returnCode, msg, extras);
            }
        };

然后

private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
        mFinalStatus = returnCode;
        mFinalMessage = msg;

        if (mRemoteObserver != null) {
            try {
                mRemoteObserver.onPackageInstalled(mPackageName, returnCode, msg, extras);
            } catch (RemoteException ignored) {
            }
        }

        final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);
        mCallback.onSessionFinished(this, success);
    }
14、PackageInstallObserverAdapter#onPackageInstalled
 @Override
1037          public void onPackageInstalled(String basePackageName, int returnCode, String msg,
1038                  Bundle extras) {
1039              if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) {
1040                  boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
1041                  Notification notification = buildSuccessNotification(mContext,
1042                          mContext.getResources()
1043                                  .getString(update ? R.string.package_updated_device_owner :
1044                                          R.string.package_installed_device_owner),
1045                          basePackageName,
1046                          mUserId);
1047                  if (notification != null) {
1048                      NotificationManager notificationManager = (NotificationManager)
1049                              mContext.getSystemService(Context.NOTIFICATION_SERVICE);
1050                      notificationManager.notify(basePackageName, 0, notification);
1051                  }
1052              }
1053              final Intent fillIn = new Intent();
1054              fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
1055              fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
1056              fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
1057                      PackageManager.installStatusToPublicStatus(returnCode));
1058              fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
1059                      PackageManager.installStatusToString(returnCode, msg));
1060              fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
1061              if (extras != null) {
1062                  final String existing = extras.getString(
1063                          PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
1064                  if (!TextUtils.isEmpty(existing)) {
1065                      fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
1066                  }
1067              }
1068              try {
1069                  mTarget.sendIntent(mContext, 0, fillIn, null, null);
1070              } catch (SendIntentException ignored) {
1071              }
1072          }
1073      }

最后可以看到,安装完成后,发送了一个广播,在luncher 注册了这个广播,然后更新页面,添加一个图标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值