Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0b0bef7 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Surface detailed error messages from PMS.

We now both log detailed error messages and relay them back to any
observer.  Start refactoring PMS to throw when errors are encountered
internally to make it easier to reason about flow control; already
uncovered a few instances of errors being silently ignored!

Change-Id: Ia335c5e31bd10243d52fd735c513ca828e83dca0
parent 030f0b23
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -73,11 +73,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.StrictJarFile;
+0 −2
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.os.Binder;
import android.os.FileUtils;
import android.os.HandlerThread;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
import android.os.UserHandle;
import android.os.UserManager;
@@ -43,7 +42,6 @@ import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.IoThread;
import com.google.android.collect.Sets;

+18 −27
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

                try {
                    installLocked();
                } catch (InstallFailedException e) {
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "Install failed: " + e);
                    destroy();
                    try {
@@ -235,16 +235,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        mHandler.obtainMessage(MSG_INSTALL, observer).sendToTarget();
    }

    private void installLocked() throws InstallFailedException {
    private void installLocked() throws PackageManagerException {
        if (mInvalid) {
            throw new InstallFailedException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
            throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
        }

        // Verify that all writers are hands-off
        if (mMutationsAllowed) {
            for (FileBridge bridge : mBridges) {
                if (!bridge.isClosed()) {
                    throw new InstallFailedException(INSTALL_FAILED_PACKAGE_CHANGED,
                    throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
                            "Files still open");
                }
            }
@@ -298,13 +298,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     * <p>
     * Renames package files in stage to match split names defined inside.
     */
    private void validateInstallLocked() throws InstallFailedException {
    private void validateInstallLocked() throws PackageManagerException {
        mPackageName = null;
        mVersionCode = -1;

        final File[] files = sessionStageDir.listFiles();
        if (ArrayUtils.isEmpty(files)) {
            throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, "No packages staged");
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
        }

        final ArraySet<String> seenSplits = new ArraySet<>();
@@ -315,12 +315,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            try {
                info = PackageParser.parseApkLite(file, PackageParser.PARSE_GET_SIGNATURES);
            } catch (PackageParserException e) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Failed to parse " + file + ": " + e);
            }

            if (!seenSplits.add(info.splitName)) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Split " + info.splitName + " was defined multiple times");
            }

@@ -344,7 +344,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                name = "split_" + info.splitName + ".apk";
            }
            if (!FileUtils.isValidExtFilename(name)) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Invalid filename: " + name);
            }
            if (!file.getName().equals(name)) {
@@ -359,7 +359,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        if (params.fullInstall) {
            // Full installs must include a base package
            if (!seenSplits.contains(null)) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Full install must include a base package");
            }

@@ -367,7 +367,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            // Partial installs must be consistent with existing install.
            final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
            if (app == null) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Missing existing base package for " + mPackageName);
            }

@@ -376,7 +376,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
                        PackageParser.PARSE_GET_SIGNATURES);
            } catch (PackageParserException e) {
                throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                        "Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
            }

@@ -386,18 +386,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    }

    private void assertPackageConsistent(String tag, String packageName, int versionCode,
            Signature[] signatures) throws InstallFailedException {
            Signature[] signatures) throws PackageManagerException {
        if (!mPackageName.equals(packageName)) {
            throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, tag + " package "
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
                    + packageName + " inconsistent with " + mPackageName);
        }
        if (mVersionCode != versionCode) {
            throw new InstallFailedException(INSTALL_FAILED_INVALID_APK, tag
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
                    + " version code " + versionCode + " inconsistent with "
                    + mVersionCode);
        }
        if (!Signature.areExactMatch(mSignatures, signatures)) {
            throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                    tag + " signatures are inconsistent");
        }
    }
@@ -406,14 +406,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     * Application is already installed; splice existing files that haven't been
     * overridden into our stage.
     */
    private void spliceExistingFilesIntoStage() throws InstallFailedException {
    private void spliceExistingFilesIntoStage() throws PackageManagerException {
        final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
        final File existingDir = new File(app.getBaseCodePath());

        try {
            linkTreeIgnoringExisting(existingDir, sessionStageDir);
        } catch (ErrnoException e) {
            throw new InstallFailedException(INSTALL_FAILED_INTERNAL_ERROR,
            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                    "Failed to splice into stage");
        }
    }
@@ -451,13 +451,4 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            mCallback.onSessionInvalid(this);
        }
    }

    private class InstallFailedException extends Exception {
        private final int error;

        public InstallFailedException(int error, String detailMessage) {
            super(detailMessage);
            this.error = error;
        }
    }
}
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm;

/** {@hide} */
public class PackageManagerException extends Exception {
    public final int error;

    public PackageManagerException(int error, String detailMessage) {
        super(detailMessage);
        this.error = error;
    }

    public PackageManagerException(int error, String detailMessage, Throwable throwable) {
        super(detailMessage, throwable);
        this.error = error;
    }
}
+216 −191

File changed.

Preview size limit exceeded, changes collapsed.