Search in sources :

Example 6 with IPackageInstallObserver2

use of android.content.pm.IPackageInstallObserver2 in project android_frameworks_base by DirtyUnicorns.

the class PackageManagerService method movePackageInternal.

private void movePackageInternal(final String packageName, final String volumeUuid, final int moveId, UserHandle user) throws PackageManagerException {
    final StorageManager storage = mContext.getSystemService(StorageManager.class);
    final PackageManager pm = mContext.getPackageManager();
    final boolean currentAsec;
    final String currentVolumeUuid;
    final File codeFile;
    final String installerPackageName;
    final String packageAbiOverride;
    final int appId;
    final String seinfo;
    final String label;
    final int targetSdkVersion;
    final PackageFreezer freezer;
    final int[] installedUserIds;
    // reader
    synchronized (mPackages) {
        final PackageParser.Package pkg = mPackages.get(packageName);
        final PackageSetting ps = mSettings.mPackages.get(packageName);
        if (pkg == null || ps == null) {
            throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
        }
        if (pkg.applicationInfo.isSystemApp()) {
            throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, "Cannot move system application");
        }
        if (pkg.applicationInfo.isExternalAsec()) {
            currentAsec = true;
            currentVolumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
        } else if (pkg.applicationInfo.isForwardLocked()) {
            currentAsec = true;
            currentVolumeUuid = "forward_locked";
        } else {
            currentAsec = false;
            currentVolumeUuid = ps.volumeUuid;
            final File probe = new File(pkg.codePath);
            final File probeOat = new File(probe, "oat");
            if (!probe.isDirectory() || !probeOat.isDirectory()) {
                throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move only supported for modern cluster style installs");
            }
        }
        if (Objects.equals(currentVolumeUuid, volumeUuid)) {
            throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Package already moved to " + volumeUuid);
        }
        if (pkg.applicationInfo.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) {
            throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, "Device admin cannot be moved");
        }
        if (mFrozenPackages.contains(packageName)) {
            throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, "Failed to move already frozen package");
        }
        codeFile = new File(pkg.codePath);
        installerPackageName = ps.installerPackageName;
        packageAbiOverride = ps.cpuAbiOverrideString;
        appId = UserHandle.getAppId(pkg.applicationInfo.uid);
        seinfo = pkg.applicationInfo.seinfo;
        label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
        targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
        freezer = freezePackage(packageName, "movePackageInternal");
        installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
    }
    final Bundle extras = new Bundle();
    extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
    extras.putString(Intent.EXTRA_TITLE, label);
    mMoveCallbacks.notifyCreated(moveId, extras);
    int installFlags;
    final boolean moveCompleteApp;
    final File measurePath;
    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
        installFlags = INSTALL_INTERNAL;
        moveCompleteApp = !currentAsec;
        measurePath = Environment.getDataAppDirectory(volumeUuid);
    } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
        installFlags = INSTALL_EXTERNAL;
        moveCompleteApp = false;
        measurePath = storage.getPrimaryPhysicalVolume().getPath();
    } else {
        final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid);
        if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE || !volume.isMountedWritable()) {
            freezer.close();
            throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move location not mounted private volume");
        }
        Preconditions.checkState(!currentAsec);
        installFlags = INSTALL_INTERNAL;
        moveCompleteApp = true;
        measurePath = Environment.getDataAppDirectory(volumeUuid);
    }
    final PackageStats stats = new PackageStats(null, -1);
    synchronized (mInstaller) {
        for (int userId : installedUserIds) {
            if (!getPackageSizeInfoLI(packageName, userId, stats)) {
                freezer.close();
                throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Failed to measure package size");
            }
        }
    }
    if (DEBUG_INSTALL)
        Slog.d(TAG, "Measured code size " + stats.codeSize + ", data size " + stats.dataSize);
    final long startFreeBytes = measurePath.getFreeSpace();
    final long sizeBytes;
    if (moveCompleteApp) {
        sizeBytes = stats.codeSize + stats.dataSize;
    } else {
        sizeBytes = stats.codeSize;
    }
    if (sizeBytes > storage.getStorageBytesUntilLow(measurePath)) {
        freezer.close();
        throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Not enough free space to move");
    }
    mMoveCallbacks.notifyStatusChanged(moveId, 10);
    final CountDownLatch installedLatch = new CountDownLatch(1);
    final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {

        @Override
        public void onUserActionRequired(Intent intent) throws RemoteException {
            throw new IllegalStateException();
        }

        @Override
        public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) throws RemoteException {
            if (DEBUG_INSTALL)
                Slog.d(TAG, "Install result for move: " + PackageManager.installStatusToString(returnCode, msg));
            installedLatch.countDown();
            freezer.close();
            final int status = PackageManager.installStatusToPublicStatus(returnCode);
            switch(status) {
                case PackageInstaller.STATUS_SUCCESS:
                    mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_SUCCEEDED);
                    break;
                case PackageInstaller.STATUS_FAILURE_STORAGE:
                    mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE);
                    break;
                default:
                    mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR);
                    break;
            }
        }
    };
    final MoveInfo move;
    if (moveCompleteApp) {
        // Kick off a thread to report progress estimates
        new Thread() {

            @Override
            public void run() {
                while (true) {
                    try {
                        if (installedLatch.await(1, TimeUnit.SECONDS)) {
                            break;
                        }
                    } catch (InterruptedException ignored) {
                    }
                    final long deltaFreeBytes = startFreeBytes - measurePath.getFreeSpace();
                    final int progress = 10 + (int) MathUtils.constrain(((deltaFreeBytes * 80) / sizeBytes), 0, 80);
                    mMoveCallbacks.notifyStatusChanged(moveId, progress);
                }
            }
        }.start();
        final String dataAppName = codeFile.getName();
        move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName, dataAppName, appId, seinfo, targetSdkVersion);
    } else {
        move = null;
    }
    installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
    final InstallParams params = new InstallParams(origin, move, installObserver, installFlags, installerPackageName, volumeUuid, null, /*verificationInfo*/
    user, packageAbiOverride, null, /*grantedPermissions*/
    null);
    params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
    msg.obj = params;
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "movePackage", System.identityHashCode(msg.obj));
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(msg.obj));
    mHandler.sendMessage(msg);
}
Also used : Message(android.os.Message) StorageManager(android.os.storage.StorageManager) VolumeInfo(android.os.storage.VolumeInfo) PackageManager(android.content.pm.PackageManager) IPackageManager(android.content.pm.IPackageManager) PackageStats(android.content.pm.PackageStats) Bundle(android.os.Bundle) Intent(android.content.Intent) CountDownLatch(java.util.concurrent.CountDownLatch) ServiceThread(com.android.server.ServiceThread) FgThread(com.android.server.FgThread) PackageParser(android.content.pm.PackageParser) IPackageInstallObserver2(android.content.pm.IPackageInstallObserver2) PackageParser.isApkFile(android.content.pm.PackageParser.isApkFile) File(java.io.File) DexFile(dalvik.system.DexFile) StrictJarFile(android.util.jar.StrictJarFile)

Example 7 with IPackageInstallObserver2

use of android.content.pm.IPackageInstallObserver2 in project android_frameworks_base by DirtyUnicorns.

the class PackageInstallerSession method commitLocked.

private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo) throws PackageManagerException {
    if (mDestroyed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
    }
    if (!mSealed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
    }
    try {
        resolveStageDir();
    } catch (IOException e) {
        throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, "Failed to resolve stage location", e);
    }
    // Verify that stage looks sane with respect to existing application.
    // This currently only ensures packageName, versionCode, and certificate
    // consistency.
    validateInstallLocked(pkgInfo, appInfo);
    Preconditions.checkNotNull(mPackageName);
    Preconditions.checkNotNull(mSignatures);
    Preconditions.checkNotNull(mResolvedBaseFile);
    if (!mPermissionsAccepted) {
        // User needs to accept permissions; give installer an intent they
        // can use to involve user.
        final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
        intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
        intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
        try {
            mRemoteObserver.onUserActionRequired(intent);
        } catch (RemoteException ignored) {
        }
        // Commit was keeping session marked as active until now; release
        // that extra refcount so session appears idle.
        close();
        return;
    }
    if (stageCid != null) {
        // Figure out the final installed size and resize the container once
        // and for all. Internally the parser handles straddling between two
        // locations when inheriting.
        final long finalSize = calculateInstalledSize();
        resizeContainer(stageCid, finalSize);
    }
    // haven't been overridden.
    if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
        try {
            final List<File> fromFiles = mResolvedInheritedFiles;
            final File toDir = resolveStageDir();
            if (LOGD)
                Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
            if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                throw new IllegalStateException("mInheritedFilesBase == null");
            }
            if (isLinkPossible(fromFiles, toDir)) {
                if (!mResolvedInstructionSets.isEmpty()) {
                    final File oatDir = new File(toDir, "oat");
                    createOatDirs(mResolvedInstructionSets, oatDir);
                }
                linkFiles(fromFiles, toDir, mInheritedFilesBase);
            } else {
                // TODO: this should delegate to DCS so the system process
                // avoids holding open FDs into containers.
                copyFiles(fromFiles, toDir);
            }
        } catch (IOException e) {
            throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed to inherit existing install", e);
        }
    }
    // TODO: surface more granular state from dexopt
    mInternalProgress = 0.5f;
    computeProgressLocked(true);
    // Unpack native libraries
    extractNativeLibraries(mResolvedStageDir, params.abiOverride);
    // Container is ready to go, let's seal it up!
    if (stageCid != null) {
        finalizeAndFixContainer(stageCid);
    }
    // We've reached point of no return; call into PMS to install the stage.
    // Regardless of success or failure we always destroy session.
    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);
        }
    };
    final UserHandle user;
    if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
        user = UserHandle.ALL;
    } else {
        user = new UserHandle(userId);
    }
    mRelinquished = true;
    mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params, installerPackageName, installerUid, user, mCertificates);
}
Also used : Bundle(android.os.Bundle) Intent(android.content.Intent) IOException(java.io.IOException) IPackageInstallObserver2(android.content.pm.IPackageInstallObserver2) UserHandle(android.os.UserHandle) RemoteException(android.os.RemoteException) File(java.io.File)

Example 8 with IPackageInstallObserver2

use of android.content.pm.IPackageInstallObserver2 in project android_frameworks_base by ResurrectionRemix.

the class PackageInstallerSession method commitLocked.

private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo) throws PackageManagerException {
    if (mDestroyed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
    }
    if (!mSealed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
    }
    try {
        resolveStageDir();
    } catch (IOException e) {
        throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, "Failed to resolve stage location", e);
    }
    // Verify that stage looks sane with respect to existing application.
    // This currently only ensures packageName, versionCode, and certificate
    // consistency.
    validateInstallLocked(pkgInfo, appInfo);
    Preconditions.checkNotNull(mPackageName);
    Preconditions.checkNotNull(mSignatures);
    Preconditions.checkNotNull(mResolvedBaseFile);
    if (!mPermissionsAccepted) {
        // User needs to accept permissions; give installer an intent they
        // can use to involve user.
        final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
        intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
        intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
        try {
            mRemoteObserver.onUserActionRequired(intent);
        } catch (RemoteException ignored) {
        }
        // Commit was keeping session marked as active until now; release
        // that extra refcount so session appears idle.
        close();
        return;
    }
    if (stageCid != null) {
        // Figure out the final installed size and resize the container once
        // and for all. Internally the parser handles straddling between two
        // locations when inheriting.
        final long finalSize = calculateInstalledSize();
        resizeContainer(stageCid, finalSize);
    }
    // haven't been overridden.
    if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
        try {
            final List<File> fromFiles = mResolvedInheritedFiles;
            final File toDir = resolveStageDir();
            if (LOGD)
                Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
            if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                throw new IllegalStateException("mInheritedFilesBase == null");
            }
            if (isLinkPossible(fromFiles, toDir)) {
                if (!mResolvedInstructionSets.isEmpty()) {
                    final File oatDir = new File(toDir, "oat");
                    createOatDirs(mResolvedInstructionSets, oatDir);
                }
                linkFiles(fromFiles, toDir, mInheritedFilesBase);
            } else {
                // TODO: this should delegate to DCS so the system process
                // avoids holding open FDs into containers.
                copyFiles(fromFiles, toDir);
            }
        } catch (IOException e) {
            throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed to inherit existing install", e);
        }
    }
    // TODO: surface more granular state from dexopt
    mInternalProgress = 0.5f;
    computeProgressLocked(true);
    // Unpack native libraries
    extractNativeLibraries(mResolvedStageDir, params.abiOverride);
    // Container is ready to go, let's seal it up!
    if (stageCid != null) {
        finalizeAndFixContainer(stageCid);
    }
    // We've reached point of no return; call into PMS to install the stage.
    // Regardless of success or failure we always destroy session.
    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);
        }
    };
    final UserHandle user;
    if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
        user = UserHandle.ALL;
    } else {
        user = new UserHandle(userId);
    }
    mRelinquished = true;
    mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params, installerPackageName, installerUid, user, mCertificates);
}
Also used : Bundle(android.os.Bundle) Intent(android.content.Intent) IOException(java.io.IOException) IPackageInstallObserver2(android.content.pm.IPackageInstallObserver2) UserHandle(android.os.UserHandle) RemoteException(android.os.RemoteException) File(java.io.File)

Aggregations

Intent (android.content.Intent)8 IPackageInstallObserver2 (android.content.pm.IPackageInstallObserver2)8 Bundle (android.os.Bundle)8 File (java.io.File)7 IOException (java.io.IOException)6 RemoteException (android.os.RemoteException)5 UserHandle (android.os.UserHandle)5 IPackageManager (android.content.pm.IPackageManager)2 PackageManager (android.content.pm.PackageManager)2 PackageParser (android.content.pm.PackageParser)2 PackageParser.isApkFile (android.content.pm.PackageParser.isApkFile)2 PackageStats (android.content.pm.PackageStats)2 Message (android.os.Message)2 StorageManager (android.os.storage.StorageManager)2 VolumeInfo (android.os.storage.VolumeInfo)2 StrictJarFile (android.util.jar.StrictJarFile)2 FgThread (com.android.server.FgThread)2 ServiceThread (com.android.server.ServiceThread)2 DexFile (dalvik.system.DexFile)2 CountDownLatch (java.util.concurrent.CountDownLatch)2