Sometimes when AM files are modified and CODE is compiled by AS, Installation Error code: -102 may appear during the Installation of packaged APK due to compilation environment. Then, at what stage does -102 error code refer to PM?

1, PackageManagerService

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

1.1 processPendingInstall catches -102 when parsing APP and cache the result into SparseArray MrunningInstall. The key is token.

    private void processPendingInstall(final InstallArgs args, final int currentStatus) {
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.returnCode = currentStatus;
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = new PackageRemovedInfo();
                if(res.returnCode == PackageManager.INSTALL_SUCCEEDED) { args.doPreInstall(res.returnCode); synchronized (mInstallLock) { installPackageLI(args, res); } args.doPostInstall(res.returncode, res.uid); }... PostInstallData data = new PostInstallData(args, res); mRunningInstalls.put(token, data); //-102 cache to SparseArray<PostInstallData> Mrunningmouse.if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip "+ token); // Pay attention to the token, when processing the POST_INSTALL message according to which -102...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); Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); mHandler.sendMessage(msg); }}Copy the code

1.2 installPackageLI Capture -102

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) { // Result object to be returned res.returnCode = PackageManager.INSTALL_SUCCEEDED; . PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setDisplayMetrics(mMetrics); final PackageParser.Package pkg; try { pkg = pp.parsePackage(tmpPackageFile, parseFlags); } catch (PackageParserException e) { res.setError("Failed parse during installPackageLI", e); // Notice the -102 exception caught herereturn; }}Copy the code

2. PackageParser throws -102

frameworks\base\core\java\android\content\pm

2.1 parsePackage throws -102

    public Package parsePackage(File packageFile, int flags) throws PackageParserException {
        if (packageFile.isDirectory()) {
            return parseClusterPackage(packageFile, flags);
        } else {
            returnparseMonolithicPackage(packageFile, flags); }}Copy the code

2.2 parseMonolithicPackage throws -102

public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
 try {
            final Package pkg = parseBaseApk(apkFile, assets, flags);
            pkg.codePath = apkFile.getAbsolutePath();
            returnpkg; } finally { IoUtils.closeQuietly(assets); }}Copy the code

2.3 parseBaseApk throws -102

Call parseBaseApk(res, Parser, Flags, outError); Raises an exception with install_parse_failed_exception = -102, caught by PackageManagerService in its installPackageLI.

    private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
            throws PackageParserException {
            try {
            res = new Resources(assets, mMetrics, null);
            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    Build.VERSION.RESOURCES_SDK_INT);
            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

            final String[] outError = new String[1];
            final Package pkg = parseBaseApk(res, parser, flags, outError);
            if (pkg == null) {
                throw new PackageParserException(mParseError,
                        apkPath + " (at " + parser.getPositionDescription() + ")." + outError[0]);
            }

            pkg.volumeUuid = volumeUuid;
            pkg.baseCodePath = apkPath;
            pkg.mSignatures = null;

            return pkg;

        } catch (PackageParserException e) {
            throw e;
        } catch (Exception e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                    "Failed to read manifest from "+ apkPath, e); } finally { IoUtils.closeQuietly(parser); }}Copy the code

3 processPendingInstall of the PMS sends the POST_INSTALL message

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

3.1 Sending a POST_INSTALL Message

  private void processPendingInstall(final InstallArgs args, final int currentStatus) {
  ...
  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); Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); mHandler.sendMessage(msg); }... }Copy the code

3.2 Notify the application layer installer

mRunningInstalls.get(msg.arg1); Fetch PostInstallData with -102 information based on token.

 class PackageHandler extends Handler {
 void doHandleMessage(Message msg) {
            switch (msg.what) {
                case POST_INSTALL: {
                    if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
                    PostInstallData data = mRunningInstalls.get(msg.arg1);
                    if(data ! = null) { InstallArgs args = data.args; PackageInstalledInfo res = data.res;if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                           if(args.observer ! = null) { try { Bundle extras = extrasForInstallResult(res); args.observer.onPackageInstalled(res.name, res.returnCode, res.returnMsg, extras); } catch (RemoteException e) {slog. I (TAG,"Observer no longer exists.");
                            }
                        }
                        }
                    }
            }
 }
Copy the code

4 Where does the Observer of PackageHandler come from

4.1 Application Layer PackageInstaller

packages/apps/PackageInstaller

public class InstallAppProgress{
    PackageInstallObserver observer = new PackageInstallObserver();
        pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}

class PackageInstallObserver extends IPackageInstallObserver.Stub {
        public void packageInstalled(String packageName, int returnCode) {
            Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
            msg.arg1 = returnCode; mHandler.sendMessage(msg); }}Copy the code

4.2 ApplicationPackageManager installPackage

frameworks\base\core\java\android\app\ApplicationPackageManager.java

    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
                               String installerPackageName) {
        final VerificationParams verificationParams = new VerificationParams(null, null,
                null, VerificationParams.NO_UID, null);
        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
                installerPackageName, verificationParams, null);
    }
Copy the code

4.3 PMS installPackage emits INIT_COPY

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

    @Override
    public void installPackage(String originPath, IPackageInstallObserver2 observer,
            int installFlags, String installerPackageName, VerificationParams verificationParams,
            String packageAbiOverride) {
        installPackageAsUser(originPath, observer, installFlags, installerPackageName,
                verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
    }
    
    public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,int installFlags, String installerPackageName, VerificationParams verificationParams, String packageAbiOverride, int userId) {
             final Message msg = mHandler.obtainMessage(INIT_COPY);
        msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
                null, verificationParams, user, packageAbiOverride, null);
        mHandler.sendMessage(msg);
    }
Copy the code

5 How to create an Observer in the PMS

 case MCS_BOUND: {
 else if (mPendingInstalls.size() > 0) {
                        HandlerParams params = mPendingInstalls.get(0);
                        if(params ! = null) {if (params.startCopy()) {
Copy the code
        final boolean startCopy() {
            boolean res;
            try {
                if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ":" + this);

                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;
        }
Copy the code
  public void handleStartCopy() throws RemoteException {
            int ret = PackageManager.INSTALL_SUCCEEDED;
             final InstallArgs args = createInstallArgs(this);
            mArgs = args;
            }
Copy the code
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); }}Copy the code

So far, the Observer of processPendingInstall is stored in MrunningMouse. If a -102 exception occurs during APP installation, the PackageInstaller can be notified.