Jimmy Chen

A Programmer

(原创)基于Android 8.1之PackageInstaller源码分析(三)

  上一篇我们讲到在PackageInstallerSession的commitLocked方法中,我们最后调用了PackageManagerService的installStage方法。这里我们直接从

PackageManagerService.java

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_INSTANT_APP) != 0) {
            Slog.d(TAG, "Ephemeral install of " + packageName);
        }
    }
    // VerificationInfo中主要是用来存储权限验证需要的信息
    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 int installReason = fixUpInstallReason(installerPackageName, installerUid,
            sessionParams.installReason);
    // 创建InstallParams对象,准备安装包所需要的安装数据
    final InstallParams params = new InstallParams(origin, null, observer,
            sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
            verificationInfo, user, sessionParams.abiOverride,
            sessionParams.grantedRuntimePermissions, certificates, installReason);
    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));

    // 向mHandler发送数据
    mHandler.sendMessage(msg);
}

  上面的代码中,在最后我们向mHandler发送了INIT_COPY,接下来我们分析mHandler是如何处理INIT_COPY的。

mHandler处理INIT_COPY

  首先在PackageManagerService初始化的时候有初始化mHandler:mHandler = new PackageHandler(mHandlerThread.getLooper());,所以这里直接查看PackageHandler相关代码。

public void handleMessage(Message msg) {
    try {
        // 调用doHandleMessage进行实际处理
        doHandleMessage(msg);
    } finally {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    }
}

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);
            // mBound用于标识是否已经绑定到服务,初始值为false
            if (!mBound) {
                Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                        System.identityHashCode(mHandler));
                // 如果还没有绑定,那调用connectToService绑定到实际的服务
                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 {
                    // 如果绑定成功,将请求添加到mPendingInstalls中,mPendingInstalls是一个ArrayList对象
                    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;
        }
    ........................

  mBound是用来标记是否已经绑定到DefaultContainerService服务,mBound的默认值是false,表示默认没有绑定到DefaultContainerService。


connectToService

private boolean connectToService() {
    if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
            " DefaultContainerService");
    // Component的包名为com.android.defcontainer,类名为com.android.defcontainer.DefaultContainerService
    Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    // 绑定DefaultContainerService,绑定成功后会调用service的onServiceConnected
    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;
}

  这里bindServiceAsUser和应用层调用bindService是一样的,当传递BIND_AUTO_CREATE后会立刻调用mDefContainerConn的onServiceConnected方法。


DefaultContainerConnection

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");
        final IMediaContainerService imcs = IMediaContainerService.Stub
                .asInterface(Binder.allowBlocking(service));
        // 发送MCS_BOUND信息,并且携带imcs
        mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
    }

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

  在onServiceConnected中,首先获取到IMediaContainerService的服务对象,然后再将该imcs服务对象附加到MCS_BOUND类型的Message中,最后再发送出去。这里再一次通过mHandler来处理数据,接下来我们分析mHandler是如何处理MCS_BOUND类型的消息的。


mHandler处理MCS_BOUND消息

..................
case MCS_BOUND: {
    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
    // 获取msg中的IMediaContainerService服务对象
    if (msg.obj != null) {
        mContainerService = (IMediaContainerService) msg.obj;
        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                System.identityHashCode(mHandler));
    }
    // mContainerService不为null
    if (mContainerService == null) {
        ..........
    // 如果mPendingInstalls中存在未处理的安装请求
    } 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");
            // 调用startCopy开始处理APK的安装,下面再分析其处理过程
            if (params.startCopy()) {
                if (DEBUG_SD_INSTALL) Log.i(TAG,
                        "Checking for more work or unbind...");
                // 处理完成,移除安装请求
                if (mPendingInstalls.size() > 0) {
                    mPendingInstalls.remove(0);
                }
                if (mPendingInstalls.size() == 0) {
                    // 如果没有已经没有安装请求了,而且DefaultContainerService还处于绑定中
                    if (mBound) {
                        if (DEBUG_SD_INSTALL) Log.i(TAG,
                                "Posting delayed MCS_UNBIND");
                        // 发送消息,解除DefaultContainerService绑定
                        removeMessages(MCS_UNBIND);
                        Message ubmsg = obtainMessage(MCS_UNBIND);
                        sendMessageDelayed(ubmsg, 10000);
                    }
                } else {
                    // mPendingInstalls中还有未处理的安装请求,继续发送MCS_BOUND消息处理
                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                            "Posting MCS_BOUND for next work");
                    mHandler.sendEmptyMessage(MCS_BOUND);
                }
            }
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    } else {
        // Should never happen ideally.
        Slog.w(TAG, "Empty queue");
    }
    break;
}
case MCS_RECONNECT: {
..............

  上面的代码都比较容易理解,我们接着分析关键部分startCopy的代码。


startCopy

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

        // MAX_RETRIES=4,代表有4次尝试安装的机会,如果超过四次就放弃这个安装请求
        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来完成所有的工作。


handleStartCopy

public void handleStartCopy() throws RemoteException {
    int ret = PackageManager.INSTALL_SUCCEEDED;

    // 根据参数设置确定应用的安装位置
    if (origin.staged) {
        if (origin.file != null) {
            installFlags |= PackageManager.INSTALL_INTERNAL;
            installFlags &= ~PackageManager.INSTALL_EXTERNAL;
        } else if (origin.cid != null) {
            installFlags |= PackageManager.INSTALL_EXTERNAL;
            installFlags &= ~PackageManager.INSTALL_INTERNAL;
        } else {
            throw new IllegalStateException("Invalid stage location");
        }
    }

    // 安装到SD卡
    final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
    // 安装到内部存储
    final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
    // 安装临时存储,Instant APP Google版小程序
    final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
    PackageInfoLite pkgLite = null;

    // 不能同时安装在内部存储以及SD卡中
    if (onInt && onSd) {
        Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
    // Instant APP不能安装到SD卡中
    } else if (onSd && ephemeral) {
        Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
    } else {
        // 通过mContainerService获取最小APK安装信息
        pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                packageAbiOverride);

        if (DEBUG_EPHEMERAL && ephemeral) {
            Slog.v(TAG, "pkgLite for install: " + pkgLite);
        }

        // 如果空间不住,尝试释放cache
        if (!origin.staged && pkgLite.recommendedInstallLocation
                == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
            // TODO: focus freeing disk space on the target device
            final StorageManager storage = StorageManager.from(mContext);
            final long lowThreshold = storage.getStorageLowBytes(
                    Environment.getDataDirectory());

            // 计算安装container的大小
            final long sizeBytes = mContainerService.calculateInstalledSize(
                    origin.resolvedPath, isForwardLocked(), packageAbiOverride);

            try {
                // 释放cache
                mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
                pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
                        installFlags, packageAbiOverride);
            } catch (InstallerException e) {
                Slog.w(TAG, "Failed to free cache", e);
            }

            // 空间依旧不够
            if (pkgLite.recommendedInstallLocation
                    == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                pkgLite.recommendedInstallLocation
                    = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
            }
        }
    }

    if (ret == PackageManager.INSTALL_SUCCEEDED) {
        int loc = pkgLite.recommendedInstallLocation;
        // 判断返回值,确认应用最后的安装路劲
        if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
            ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
        } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
            ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
        } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
            ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
        } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
            ret = PackageManager.INSTALL_FAILED_INVALID_APK;
        } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
            ret = PackageManager.INSTALL_FAILED_INVALID_URI;
        } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
            ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
        } else {
            // 调用installLocationPolicy判断最终的安装路径
            // installLocationPolicy主要判断终端上是否有已经安装过该APK,同一个APK一般只能用新版的替换旧版
            loc = installLocationPolicy(pkgLite);
            if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
                ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
            } else if (!onSd && !onInt) {
                // Override install location with flags
                if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                    // Set the flag to install on external media.
                    installFlags |= PackageManager.INSTALL_EXTERNAL;
                    installFlags &= ~PackageManager.INSTALL_INTERNAL;
                } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
                    if (DEBUG_EPHEMERAL) {
                        Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
                    }
                    installFlags |= PackageManager.INSTALL_INSTANT_APP;
                    installFlags &= ~(PackageManager.INSTALL_EXTERNAL
                            |PackageManager.INSTALL_INTERNAL);
                } else {
                    // Make sure the flag for installing on external
                    // media is unset
                    installFlags |= PackageManager.INSTALL_INTERNAL;
                    installFlags &= ~PackageManager.INSTALL_EXTERNAL;
                }
            }
        }
    }

    // 在上面确认完安装路径后,调用createInstallArgs来创建一个安装参数对象
    final InstallArgs args = createInstallArgs(this);
    mArgs = args;

    if (ret == PackageManager.INSTALL_SUCCEEDED) {
        // 如果是为所有用户安装,就调用设备拥有者来校验安装此应用
        UserHandle verifierUser = getUser();
        if (verifierUser == UserHandle.ALL) {
            verifierUser = UserHandle.SYSTEM;
        }

        /*
         * Determine if we have any installed package verifiers. If we
         * do, then we'll defer to them to verify the packages.
         */
        final int requiredUid = mRequiredVerifierPackage == null ? -1
                : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                        verifierUser.getIdentifier());

        final int optionalUid = mOptionalVerifierPackage == null ? -1
                : getPackageUid(mOptionalVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                        verifierUser.getIdentifier());

        final int installerUid =
                verificationInfo == null ? -1 : verificationInfo.installerUid;
        // 检查是否需要执行验证,正常情况下通过adb安装应用以及是首先用户执行应用安装才需要执行验证
        if (!origin.existing && (requiredUid != -1 || optionalUid != -1)
                && isVerificationEnabled(
                        verifierUser.getIdentifier(), installFlags, installerUid)) {
          ................................
        } else {
            // 调用安装参数对象的copyApk方法执行安装。
            ret = args.copyApk(mContainerService, true);
        }
    }

    mRet = ret;
}

  这上面的代码内容很多,这里尽量对其中一些函数做分析。

1. handleStartCopy -> getMinimalPackageInfo

public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags,
        String abiOverride) {
    // 获取DefaultContainerService服务对象
    final Context context = DefaultContainerService.this;
    final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;

    // 创建应用包信息对象
    PackageInfoLite ret = new PackageInfoLite();
    if (packagePath == null) {
        Slog.i(TAG, "Invalid package file " + packagePath);
        ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
        return ret;
    }

    final File packageFile = new File(packagePath);
    final PackageParser.PackageLite pkg;
    final long sizeBytes;
    try {
        // 创建PackageLite
        pkg = PackageParser.parsePackageLite(packageFile, 0);
        // 计算安装APK所需存储空间大小
        sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
    } catch (PackageParserException | IOException e) {
        Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);

        if (!packageFile.exists()) {
            ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI;
        } else {
            ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
        }

        return ret;
    }

    final int recommendedInstallLocation;
    final long token = Binder.clearCallingIdentity();
    try {
        // 调用resolveInstallLocation确定应用安装位置
        recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
                pkg.packageName, pkg.installLocation, sizeBytes, flags);
    } finally {
        Binder.restoreCallingIdentity(token);
    }

    ret.packageName = pkg.packageName;
    ret.splitNames = pkg.splitNames;
    ret.versionCode = pkg.versionCode;
    ret.baseRevisionCode = pkg.baseRevisionCode;
    ret.splitRevisionCodes = pkg.splitRevisionCodes;
    ret.installLocation = pkg.installLocation;
    ret.verifiers = pkg.verifiers;
    ret.recommendedInstallLocation = recommendedInstallLocation;
    ret.multiArch = pkg.multiArch;

    return ret;
}

  这里对最终的安装路径感兴趣,所以继续最终下去,接着看resolveInstallLocation的代码

1.1 getMinimalPackageInfo -> resolveInstallLocation

public static int resolveInstallLocation(Context context, String packageName,
        int installLocation, long sizeBytes, int installFlags) {
    // 创建SessionParams,并填充其中的参数
    final SessionParams params = new SessionParams(SessionParams.MODE_INVALID);
    params.appPackageName = packageName;
    params.installLocation = installLocation;
    params.sizeBytes = sizeBytes;
    params.installFlags = installFlags;
    try {
        // 调用同名重载方法
        return resolveInstallLocation(context, params);
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }
}

public static int resolveInstallLocation(Context context, SessionParams params)
        throws IOException {
    ApplicationInfo existingInfo = null;
    try {
        // 通过PackageManager查看是否已安装同名的应用
        existingInfo = context.getPackageManager().getApplicationInfo(params.appPackageName,
                PackageManager.MATCH_ANY_USER);
    } catch (NameNotFoundException ignored) {
    }

    final int prefer;
    final boolean checkBoth;
    boolean ephemeral = false;
    // Instant APP安装到内部存储,checkBoth表示不需要再次确认
    if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
        prefer = RECOMMEND_INSTALL_INTERNAL;
        ephemeral = true;
        checkBoth = false;
    } else if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
        prefer = RECOMMEND_INSTALL_INTERNAL;
        checkBoth = false;
    } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
        prefer = RECOMMEND_INSTALL_EXTERNAL;
        checkBoth = false;
    } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
        prefer = RECOMMEND_INSTALL_INTERNAL;
        checkBoth = false;
    } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
        prefer = RECOMMEND_INSTALL_EXTERNAL;
        checkBoth = true;
    // 大部分情况下,AndroidManifest中定义的为AUTO
    } else if (params.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
        // 如果APP已经安装过,那么倾向于和原安装路径保持一致
        if (existingInfo != null) {
            if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                prefer = RECOMMEND_INSTALL_EXTERNAL;
            } else {
                prefer = RECOMMEND_INSTALL_INTERNAL;
            }
        } else {
            // 否则新安装应用安装到内部存储
            prefer = RECOMMEND_INSTALL_INTERNAL;
        }
        checkBoth = true;
    } else {
        prefer = RECOMMEND_INSTALL_INTERNAL;
        checkBoth = false;
    }

    boolean fitsOnInternal = false;
    // fitsOnInternal和fitsOnExternal用来确认prefer指定的安装路径是否有足够存储空间进行安装
    if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) {
        fitsOnInternal = fitsOnInternal(context, params);
    }

    boolean fitsOnExternal = false;
    if (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL) {
        fitsOnExternal = fitsOnExternal(context, params);
    }

    if (prefer == RECOMMEND_INSTALL_INTERNAL) {
        // The ephemeral case will either fit and return EPHEMERAL, or will not fit
        // and will fall through to return INSUFFICIENT_STORAGE
        if (fitsOnInternal) {
            return (ephemeral)
                    ? PackageHelper.RECOMMEND_INSTALL_EPHEMERAL
                    : PackageHelper.RECOMMEND_INSTALL_INTERNAL;
        }
    } else if (prefer == RECOMMEND_INSTALL_EXTERNAL) {
        if (fitsOnExternal) {
            return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
        }
    }

    if (checkBoth) {
        if (fitsOnInternal) {
            return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
        } else if (fitsOnExternal) {
            return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
        }
    }

    // 如果上面都没有返回,则表示存储空间不足
    return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
}

  上面显示了安装路径的确认过程。现在我们再次返回handleStartCopy方法中,接着我们分析handleStartCopy方法中的createInstallArgs方法。这个方法会根据安装路径来创建不同的参数对象,源码如下

2. handleStartCopy -> createInstallArgs

private InstallArgs createInstallArgs(InstallParams params) {
    // move表示安装路径在内置存储和外置存储间迁移
    if (params.move != null) {
        return new MoveInstallArgs(params);
    // AESC表示安装路径为SD卡
    } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
        return new AsecInstallArgs(params);
    // File表示安装到内置存储空间
    } else {
        return new FileInstallArgs(params);
    }
}

  InstallArgs是一个抽象类,定义了应用的安装逻辑。MoveInstallArgs、AsecInstallArgs和FileInstallArgs三个类都是InstallArgs的子类。这里确认使用FileInstallArgs,所以我们接着回到handleStartCopy方法中,分析args.copyApk方法。args表示的就是一个FileInstallArgs对象,所以这里调用的是FileInstallArgs的copyApk方法。


FileInstallArgs.copyApk

int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
    try {
        // 直接调用doCopyApk完成所需操作
        return doCopyApk(imcs, temp);
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

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 {
        // 非Instate APP
        final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
        // 创建要给临时路径
        // 临时路径一般为/data/app/xxxxxxxxxx.tmp
        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;
    }

    // 定义回调接口
    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());
            }
        }
    };

    // 调用DefaultContainerService的copyPackage方法进行package复制操作,同时将回调接口传入
    int ret = PackageManager.INSTALL_SUCCEEDED;
    ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
    if (ret != PackageManager.INSTALL_SUCCEEDED) {
        Slog.e(TAG, "Failed to copy package");
        return ret;
    }

    // 复制APK里面的native库文件
    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;
}

  上面调用DefaultContainerService的copyPackage方法进行Package的复制操作,所以我们看看copyPackage完成什么操作。

doCopyApk -> copyPackage

public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {
    // 如果源文件或者目标文件为null,返回安装出错标志
    if (packagePath == null || target == null) {
        return PackageManager.INSTALL_FAILED_INVALID_URI;
    }

    PackageLite pkg = null;
    try {
        final File packageFile = new File(packagePath);
        // 老方法了,获取安装包信息
        pkg = PackageParser.parsePackageLite(packageFile, 0);
        // 调用copyPackageInner方法进行实际复制操作
        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 {
    // 将package的baseCodePath复制到目标地址并命名为base.apk
    copyFile(pkg.baseCodePath, target, "base.apk");
    // 如果使用了APK拆分技术,就执行下面这一段
    if (!ArrayUtils.isEmpty(pkg.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 {
        //目的文件作为输出,这里进行了多层封装
        //回调接口target调用open函数后,将创建并打开目的端文件,然后赋予相应的写权限
        //ParcelFileDescriptor.AutoCloseOutputStream利用文件描述符构造出一个可自动关闭的输出流
        in = new FileInputStream(sourcePath);
        out = new ParcelFileDescriptor.AutoCloseOutputStream(
                target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
        // 进行实际复制操作
        Streams.copy(in, out);
    } finally {
        IoUtils.closeQuietly(out);
        IoUtils.closeQuietly(in);
    }
}

  handleStartCopy的所有流程到这里就结束了,接着我们返回到最前面的startCopy函数处,还有一个方法调用没有解析,那就是handleReturnCode方法了,接下来让我们继续go on


handleReturnCode

void handleReturnCode() {
    if (mArgs != null) {
        processPendingInstall(mArgs, mRet);
    }
}

  这上面的mArgs是一个FileInstallArgs对象,代表一个安装参数对象。

processPendingInstall

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    // 因为引用安装消耗时间可能较长,所以这里创建一个异步操作
    mHandler.post(new Runnable() {
        public void run() {
            mHandler.removeCallbacks(this);
            // 安装结果信息对象
            PackageInstalledInfo res = new PackageInstalledInfo();
            res.setReturnCode(currentStatus);
            res.uid = -1;
            res.pkg = null;
            res.removedInfo = null;
            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                // 安装前处理
                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);

            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
                // 调用backup接口进行恢复
                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) {
                if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

                Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
                // 发出一个POST_INSTALL消息,触发后续的操作
                Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                mHandler.sendMessage(msg);
            }
        }
    });
}

安装前处理doPreInstall

int doPreInstall(int status) {
    if (status != PackageManager.INSTALL_SUCCEEDED) {
        cleanUp();
    }
    return status;
}

private boolean cleanUp() {
    if (codeFile == null || !codeFile.exists()) {
        return false;
    }

    removeCodePathLI(codeFile);

    if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
        resourceFile.delete();
    }

    return true;
}

void removeCodePathLI(File codePath) {
    if (codePath.isDirectory()) {
        try {
            mInstaller.rmPackageDir(codePath.getAbsolutePath());
        } catch (InstallerException e) {
            Slog.w(TAG, "Failed to remove code path", e);
        }
    } else {
        codePath.delete();
    }
}

  这里有个疑问就是,在执行doPreInstall前就已经判断过status是否为PackageManager.INSTALL_SUCCEEDED,只有status等于PackageManager.INSTALL_SUCCEEDED才会执行doPreInstall操作。为什么在doPreInstall里面还要多此一举呢?这里估计res.returnCode这个返回值是可以在多处被修改的,所以可能在整个安装过程中这个值被修改了,例如在此之前可能还在执行正常的安装,但是到执行doPreInstall的时候,用户突然点击了Cancel按钮。

安装实际操作 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);
    }
}

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
    // 获取安装标志位
    final int installFlags = args.installFlags;
    final String installerPackageName = args.installerPackageName;
    final String volumeUuid = args.volumeUuid;
    final File tmpPackageFile = new File(args.getCodePath());
    // 根据安装标志位定义一些Boolean变量
    final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
    final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
            || (args.volumeUuid != null));
    final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
    final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
    final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
    final boolean virtualPreload =
            ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
    boolean replace = false;
    int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
    if (args.move != null) {
        // moving a complete application; perform an initial scan on the new install location
        scanFlags |= SCAN_INITIAL;
    }
    if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
        scanFlags |= SCAN_DONT_KILL_APP;
    }
    if (instantApp) {
        scanFlags |= SCAN_AS_INSTANT_APP;
    }
    if (fullApp) {
        scanFlags |= SCAN_AS_FULL_APP;
    }
    if (virtualPreload) {
        scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
    }

    // 设置默认安装返回值为INSTALL_SUCCEEDED
    res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
    // 安装包包名
    res.installerPackageName = installerPackageName;

    if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);

    // 完整性检查
    if (instantApp && (forwardLocked || onExternal)) {
        Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked
                + " external=" + onExternal);
        res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
        return;
    }

    // Retrieve PackageSettings and parse package
    final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
            | PackageParser.PARSE_ENFORCE_CODE
            | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
            | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
            | (instantApp ? PackageParser.PARSE_IS_EPHEMERAL : 0)
            | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
    
    // 创建PackagePaser
    PackageParser pp = new PackageParser();
    pp.setSeparateProcesses(mSeparateProcesses);
    pp.setDisplayMetrics(mMetrics);
    pp.setCallback(mPackageParserCallback);

    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
    final PackageParser.Package pkg;
    try {
        // 解析APK文件,获取Package信息
        pkg = pp.parsePackage(tmpPackageFile, parseFlags);
    } catch (PackageParserException e) {
        res.setError("Failed parse during installPackageLI", e);
        return;
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }

    // 检查系统是否符合安装Instant APP的要求
    if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
        Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");
        res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                "Instant app package must target O");
        return;
    }
    if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
        Slog.w(TAG, "Instant app package " + pkg.packageName
                + " does not target targetSandboxVersion 2");
        res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                "Instant app package must use targetSanboxVersion 2");
        return;
    }

    // 安装静态共享库
    if (pkg.applicationInfo.isStaticSharedLibrary()) {
        // Static shared libraries have synthetic package names
        renameStaticSharedLibraryPackage(pkg);

        // No static shared libs on external storage
        if (onExternal) {
            Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
            res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                    "Packages declaring static-shared libs cannot be updated");
            return;
        }
    }

    // 安装一簇安装包的时候,需要记录child package的安装情况
    if (pkg.childPackages != null) {
        synchronized (mPackages) {
            final int childCount = pkg.childPackages.size();
            for (int i = 0; i < childCount; i++) {
                PackageParser.Package childPkg = pkg.childPackages.get(i);
                PackageInstalledInfo childRes = new PackageInstalledInfo();
                childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                childRes.pkg = childPkg;
                childRes.name = childPkg.packageName;
                PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                if (childPs != null) {
                    childRes.origUsers = childPs.queryInstalledUsers(
                            sUserManager.getUserIds(), true);
                }
                if ((mPackages.containsKey(childPkg.packageName))) {
                    childRes.removedInfo = new PackageRemovedInfo(this);
                    childRes.removedInfo.removedPackage = childPkg.packageName;
                    childRes.removedInfo.installerPackageName = childPs.installerPackageName;
                }
                if (res.addedChildPackages == null) {
                    res.addedChildPackages = new ArrayMap<>();
                }
                res.addedChildPackages.put(childPkg.packageName, childRes);
            }
        }
    }

    // CPU ABI处理
    if (TextUtils.isEmpty(pkg.cpuAbiOverride)) {
        pkg.cpuAbiOverride = args.abiOverride;
    }

    // APK标记为仅用于测试时的执行逻辑
    String pkgName = res.name = pkg.packageName;
    if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
        if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
            res.setError(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
            return;
        }
    }

    try {
        // 如果还没解析到APK的安装签名证书
        if (args.certificates != null) {
            try {
                // 获取APK的签名帧数
                PackageParser.populateCertificates(pkg, args.certificates);
            } catch (PackageParserException e) {
                // there was something wrong with the certificates we were given;
                // try to pull them from the APK
                PackageParser.collectCertificates(pkg, parseFlags);
            }
        } else {
            PackageParser.collectCertificates(pkg, parseFlags);
        }
    } catch (PackageParserException e) {
        res.setError("Failed collect during installPackageLI", e);
        return;
    }

    pp = null;
    String oldCodePath = null;
    boolean systemApp = false;
    synchronized (mPackages) {
        // 检查是否已经安装过该安装包
        if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            String oldName = mSettings.getRenamedPackageLPr(pkgName);
            if (pkg.mOriginalPackages != null
                    && pkg.mOriginalPackages.contains(oldName)
                    && mPackages.containsKey(oldName)) {
                // 该安装包是来自一个原始包的,而且设备已经从原始包升级而来
                // 这里需要继续使用原始包的包名
                pkg.setPackageName(oldName);
                pkgName = pkg.packageName;
                replace = true;
                if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
                        + oldName + " pkgName=" + pkgName);
            } else if (mPackages.containsKey(pkgName)) {
                // 设置为替换
                replace = true;
                if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
            }

            // Child packages are installed through the parent package
            if (pkg.parentPackage != null) {
                res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                        "Package " + pkg.packageName + " is child of package "
                                + pkg.parentPackage.parentPackage + ". Child packages "
                                + "can be updated only through the parent package.");
                return;
            }

            // 如果需要替换
            if (replace) {
                // 阻止安装包的TargetSdk降级,以逃避运行时权限检查
                PackageParser.Package oldPackage = mPackages.get(pkgName);
                final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
                final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
                if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
                        && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                    res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
                            "Package " + pkg.packageName + " new target SDK " + newTargetSdk
                                    + " doesn't support runtime permissions but the old"
                                    + " target SDK " + oldTargetSdk + " does.");
                    return;
                }
                // 防止应用降低SandBox的版本
                final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
                final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
                if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
                    res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                            "Package " + pkg.packageName + " new target sandbox "
                            + newTargetSandbox + " is incompatible with the previous value of"
                            + oldTargetSandbox + ".");
                    return;
                }

                // 防止直接安装子程序
                if (oldPackage.parentPackage != null) {
                    res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                            "Package " + pkg.packageName + " is child of package "
                                    + oldPackage.parentPackage + ". Child packages "
                                    + "can be updated only through the parent package.");
                    return;
                }
            }
        }

        PackageSetting ps = mSettings.mPackages.get(pkgName);
        // 查看Setting中是否存在要安装的APK的信息,如果有就获取安装包对应的信息
        if (ps != null) {
            if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);

            // 可以存在多个静态共享库,在安装时需要检查其签名是否正确
            PackageSetting signatureCheckPs = ps;
            if (pkg.applicationInfo.isStaticSharedLibrary()) {
                SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
                if (libraryEntry != null) {
                    signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
                }
            }

            // 检查应用签名是否正确
            if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {
                if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) {
                    res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                            + pkg.packageName + " upgrade keys do not match the "
                            + "previously installed version");
                    return;
                }
            } else {
                try {
                    verifySignaturesLP(signatureCheckPs, pkg);
                } catch (PackageManagerException e) {
                    res.setError(e.error, e.getMessage());
                    return;
                }
            }

            // 检查该应用是否是systemApp
            oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
            if (ps.pkg != null && ps.pkg.applicationInfo != null) {
                systemApp = (ps.pkg.applicationInfo.flags &
                        ApplicationInfo.FLAG_SYSTEM) != 0;
            }
            res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
        }

        // 获取APK中的申明使用的权限
        int N = pkg.permissions.size();
        for (int i = N-1; i >= 0; i--) {
            PackageParser.Permission perm = pkg.permissions.get(i);
            BasePermission bp = mSettings.mPermissions.get(perm.info.name);

            // 仅允许systemApp定义ephemeral权限
            if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
                    && !systemApp) {
                Slog.w(TAG, "Non-System package " + pkg.packageName
                        + " attempting to delcare ephemeral permission "
                        + perm.info.name + "; Removing ephemeral.");
                perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT;
            }
            // 检查新安装的应用是否定义了已经定义过的权限
            if (bp != null) {
                // If the defining package is signed with our cert, it's okay.  This
                // also includes the "updating the same package" case, of course.
                // "updating same package" could also involve key-rotation.
                final boolean sigsOk;
                if (bp.sourcePackage.equals(pkg.packageName)
                        && (bp.packageSetting instanceof PackageSetting)
                        && (shouldCheckUpgradeKeySetLP((PackageSetting) bp.packageSetting,
                                scanFlags))) {
                    sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
                } else {
                    sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
                            pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
                }
                if (!sigsOk) {
                    // If the owning package is the system itself, we log but allow
                    // install to proceed; we fail the install on all other permission
                    // redefinitions.
                    if (!bp.sourcePackage.equals("android")) {
                        res.setError(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package "
                                + pkg.packageName + " attempting to redeclare permission "
                                + perm.info.name + " already owned by " + bp.sourcePackage);
                        res.origPermission = perm.info.name;
                        res.origPackage = bp.sourcePackage;
                        return;
                    } else {
                        Slog.w(TAG, "Package " + pkg.packageName
                                + " attempting to redeclare system permission "
                                + perm.info.name + "; ignoring new declaration");
                        pkg.permissions.remove(i);
                    }
                } else if (!PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) {
                    // 防止将protection级别的权限改为dangerous级别的权限
                    if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                            == PermissionInfo.PROTECTION_DANGEROUS) {
                        if (bp != null && !bp.isRuntime()) {
                            Slog.w(TAG, "Package " + pkg.packageName + " trying to change a "
                                    + "non-runtime permission " + perm.info.name
                                    + " to runtime; keeping old protection level");
                            perm.info.protectionLevel = bp.protectionLevel;
                        }
                    }
                }
            }
        }
    }

    if (systemApp) {
        if (onExternal) {
            // 系统APP不能升级安装到SD卡中
            res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                    "Cannot install updates to system apps on sdcard");
            return;
        } else if (instantApp) {
            // 系统APP不能升级替换为Instant APP
            res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
                    "Cannot update a system app with an instant app");
            return;
        }
    }

    // 迁移应用,这里不是先略过
    if (args.move != null) {
        ................
    }

    // 重命名应用
    // 重命名应用会从原来的临时目录/data/app/xxxxxxxxxx.tmp修改为/data/app/包名-1/base.apk
    // 其中-1代码安装的版本好,如果在此基础上进行了一次update升级安装的话,这个-1会变成-2
    if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
        res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
        return;
    }

    // 检查是否要进行dex优化
    // 优化的条件是1、没有添加前向索 2、不是安装在外置存储 3、不是Instant APP或者稍后会进行DEX优化
    final boolean performDexopt = !forwardLocked
        && !pkg.applicationInfo.isExternalAsec()
        && (!instantApp || Global.getInt(mContext.getContentResolver(),
                Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0);

    if (performDexopt) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");

        DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName,
            REASON_INSTALL,
            DexoptOptions.DEXOPT_BOOT_COMPLETE);
        mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
            null /* instructionSets */,
            getOrCreateCompilerPackageStats(pkg),
            mDexManager.getPackageUseInfoOrDefault(pkg.packageName),
            dexoptOptions);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }

    BackgroundDexOptService.notifyPackageChanged(pkg.packageName);

    startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);

    try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
            "installPackageLI")) {
        // 替换安装
        if (replace) {
            if (pkg.applicationInfo.isStaticSharedLibrary()) {
                PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
                if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
                    res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
                            + "static-shared libs cannot be updated");
                    return;
                }
            }
            // 用新的Package替换旧的Package
            replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                    installerPackageName, res, args.installReason);
        } else {
            // 将新的Package信息添加到PKMS中
            installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
                    args.user, installerPackageName, volumeUuid, res, args.installReason);
        }
    }

    synchronized (mPackages) {
        // 下面更新应用程序所属的用户
        final PackageSetting ps = mSettings.mPackages.get(pkgName);
        if (ps != null) {
            res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
            ps.setUpdateAvailable(false /*updateAvailable*/);
        }

        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
        for (int i = 0; i < childCount; i++) {
            PackageParser.Package childPkg = pkg.childPackages.get(i);
            PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
            PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
            if (childPs != null) {
                childRes.newUsers = childPs.queryInstalledUsers(
                        sUserManager.getUserIds(), true);
            }
        }

        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
            updateSequenceNumberLP(ps, res.newUsers);
            updateInstantAppInstallerLocked(pkgName);
        }
    }
}

  这一段代码比较长,博主能看懂能解释的都尽量解释了。因为我们这里假设的是安装过程,所以我们接下来看安装应用调用的方法installNewPackageLIF。

installPackageLI -> installNewPackageLIF

private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
        int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
        PackageInstalledInfo res, int installReason) {
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");

    // 获取包名
    String pkgName = pkg.packageName;

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

    synchronized(mPackages) {
        final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
        if (renamedPackage != null) {
            // 如果之前有安装过相同包名,但是已将包名改为其他包名的应用我们将其视为re-install
            res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                    + " without first uninstalling package running as "
                    + renamedPackage);
            return;
        }
        if (mPackages.containsKey(pkgName)) {
            // 重安装应用
            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, installReason);

        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
            // 为新应用准备数据
            prepareAppDataAfterInstallLIF(newPackage);

        } else {
            // 如果安装失败了则清除安装数据。
            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);
}

  最后我们还有一个POST_INSTALL消息还没处理,接下来我们查看POST_INSTALL消息是如何处理的

POST_INSTALL消息处理

    case POST_INSTALL: {
        if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);

        PostInstallData data = mRunningInstalls.get(msg.arg1);
        final boolean didRestore = (msg.arg2 != 0);
        mRunningInstalls.delete(msg.arg1);

        if (data != null) {
            InstallArgs args = data.args;
            PackageInstalledInfo parentRes = data.res;

            final boolean grantPermissions = (args.installFlags
                    & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
            final boolean killApp = (args.installFlags
                    & PackageManager.INSTALL_DONT_KILL_APP) == 0;
            final boolean virtualPreload = ((args.installFlags
                    & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
            final String[] grantedPermissions = args.installGrantPermissions;

            // 调用handlePackagePostInstall处理父安装包
            handlePackagePostInstall(parentRes, grantPermissions, killApp,
                    virtualPreload, grantedPermissions, didRestore,
                    args.installerPackageName, args.observer);

            // 同样调用handlePackagePostInstall处理自安装包
            final int childCount = (parentRes.addedChildPackages != null)
                    ? parentRes.addedChildPackages.size() : 0;
            for (int i = 0; i < childCount; i++) {
                PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
                handlePackagePostInstall(childRes, grantPermissions, killApp,
                        virtualPreload, grantedPermissions, false /*didRestore*/,
                        args.installerPackageName, args.observer);
            }

            // Log tracing if needed
            if (args.traceMethod != null) {
                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
                        args.traceCookie);
            }
        } else {
            Slog.e(TAG, "Bogus post-install token " + msg.arg1);
        }

        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);
    } break;

  handlePackagePostInstall是我们需要分析的最后一个函数了,再坚持一下把它看完吧。

handlePackagePostInstall

private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
        boolean killApp, boolean virtualPreload, String[] grantedPermissions,
        boolean launchedForRestore, String installerPackage,
        IPackageInstallObserver2 installObserver) {
    if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
        // 如果是移除应用,发送应用移除广播
        if (res.removedInfo != null) {
            res.removedInfo.sendPackageRemovedBroadcasts(killApp);
        }

        // 获取运行时权限
        if (grantPermissions) {
            grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions);
        }

        final boolean update = res.removedInfo != null
                && res.removedInfo.removedPackage != null;
        final String installerPackageName =
                res.installerPackageName != null
                        ? res.installerPackageName
                        : res.removedInfo != null
                                ? res.removedInfo.installerPackageName
                                : null;

        if (res.pkg.parentPackage != null) {
            synchronized (mPackages) {
                grantRuntimePermissionsGrantedToDisabledPrivSysPackageParentLPw(res.pkg);
            }
        }

        .........................

        // 如果不是一个静态共享库的话发送安装成功的广播
        if (res.pkg.staticSharedLibName == null) {
            mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);

            int appId = UserHandle.getAppId(res.uid);
            boolean isSystem = res.pkg.applicationInfo.isSystemApp();
            sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
                    virtualPreload /*startReceiver*/, appId, firstUsers);

            Bundle extras = new Bundle(1);
            extras.putInt(Intent.EXTRA_UID, res.uid);
            if (update) {
                extras.putBoolean(Intent.EXTRA_REPLACING, true);
            }
            // 发送ACTION_PACKAGE_ADDED广播
            sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                    extras, 0 /*flags*/,
                    null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);
            if (installerPackageName != null) {
                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                        extras, 0 /*flags*/,
                        installerPackageName, null /*finishedReceiver*/, updateUsers);
            }

            // 如果时升级应用,升级成功的话发送ACTION_PACKAGE_REPLACED广播
            if (update) {
                sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                        packageName, extras, 0 /*flags*/,
                        null /*targetPackage*/, null /*finishedReceiver*/,
                        updateUsers);
                if (installerPackageName != null) {
                    sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
                            extras, 0 /*flags*/,
                            installerPackageName, null /*finishedReceiver*/, updateUsers);
                }
                sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
                        null /*package*/, null /*extras*/, 0 /*flags*/,
                        packageName /*targetPackage*/,
                        null /*finishedReceiver*/, updateUsers);
            } else if (launchedForRestore && !isSystemApp(res.pkg)) {
                if (DEBUG_BACKUP) {
                    Slog.i(TAG, "Post-restore of " + packageName
                            + " sending FIRST_LAUNCH in " + Arrays.toString(firstUsers));
                }
                sendFirstLaunchBroadcast(packageName, installerPackage, firstUsers);
            }

            if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {
                if (DEBUG_INSTALL) {
                    Slog.i(TAG, "upgrading pkg " + res.pkg
                            + " is ASEC-hosted -> AVAILABLE");
                }
                final int[] uidArray = new int[]{res.pkg.applicationInfo.uid};
                ArrayList<String> pkgList = new ArrayList<>(1);
                pkgList.add(packageName);
                sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null);
            }
        }

        ........................

    // 将安装结果放回给pm.java中的观察者
    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.");
        }
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d 博主赞过: