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

Commit f012a22a authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

Add support for uninstalling apex to PackageManagerShellCommand

Since uninstalling apexes is development/testing operation, only root
and shell are allowed to perform it.

Test: adb uninstall + adb reboot
Bug: 123667725
Change-Id: Ifd7b743b2581dbdeebd63c33fd343a830dfc377a
parent 6deeabb6
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.ComponentInfoFlags;
import android.content.pm.PackageManager.PackageInfoFlags;
@@ -925,4 +926,21 @@ public abstract class PackageManagerInternal {
     * @param provider the provider
     */
    public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider);

    /**
     * Returns {@code true} if given {@code packageName} is an apex package.
     */
    public abstract boolean isApexPackage(String packageName);

    /**
     * Uninstalls given {@code packageName}.
     *
     * @param packageName apex package to uninstall.
     * @param versionCode version of a package to uninstall.
     * @param userId user to uninstall apex package for. Must be
     *               {@link android.os.UserHandle#USER_ALL}, otherwise failure will be reported.
     * @param intentSender a {@link IntentSender} to send result of an uninstall to.
     */
    public abstract void uninstallApex(String packageName, long versionCode, int userId,
            IntentSender intentSender);
}
+29 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -134,6 +135,17 @@ class ApexManager {
        return mActivePackagesCache.values();
    }

    /**
     * Checks if {@code packageName} is an apex package.
     *
     * @param packageName package to check.
     * @return {@code true} if {@code packageName} is an apex package.
     */
    boolean isApexPackage(String packageName) {
        populateActivePackagesCacheIfNeeded();
        return mActivePackagesCache.containsKey(packageName);
    }

    /**
     * Retrieves information about an apexd staged session i.e. the internal state used by apexd to
     * track the different states of a session.
@@ -245,6 +257,23 @@ class ApexManager {
        }
    }

    /**
     * Uninstalls given {@code apexPackage}.
     *
     * <p>NOTE. Device must be rebooted in order for uninstall to take effect.
     *
     * @param apexPackagePath package to uninstall.
     * @return {@code true} upon successful uninstall, {@code false} otherwise.
     */
    boolean uninstallApex(String apexPackagePath) {
        try {
            mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Dumps various state information to the provided {@link PrintWriter} object.
     *
+44 −0
Original line number Diff line number Diff line
@@ -23902,6 +23902,50 @@ public class PackageManagerService extends IPackageManager.Stub
                mDefaultHomeProvider = provider;
            }
        }
        @Override
        public boolean isApexPackage(String packageName) {
            return PackageManagerService.this.mApexManager.isApexPackage(packageName);
        }
        @Override
        public void uninstallApex(String packageName, long versionCode, int userId,
                IntentSender intentSender) {
            final int callerUid = Binder.getCallingUid();
            if (callerUid != Process.ROOT_UID && callerUid != Process.SHELL_UID) {
                throw new SecurityException("Not allowed to uninstall apexes");
            }
            PackageInstallerService.PackageDeleteObserverAdapter adapter =
                    new PackageInstallerService.PackageDeleteObserverAdapter(
                            PackageManagerService.this.mContext, intentSender, packageName,
                            false, userId);
            if (userId != UserHandle.USER_ALL) {
                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
                        "Can't uninstall an apex for a single user");
                return;
            }
            final ApexManager am = PackageManagerService.this.mApexManager;
            PackageInfo activePackage = am.getActivePackage(packageName);
            if (activePackage == null) {
                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
                        packageName + " is not an apex package");
                return;
            }
            if (versionCode != PackageManager.VERSION_CODE_HIGHEST
                    && activePackage.getLongVersionCode() != versionCode) {
                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
                        "Active version " + activePackage.getLongVersionCode()
                                + " is not equal to " + versionCode + "]");
                return;
            }
            if (!am.uninstallApex(activePackage.applicationInfo.sourceDir)) {
                adapter.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_ABORTED,
                        "Failed to uninstall apex " + packageName);
            } else {
                adapter.onPackageDeleted(packageName, PackageManager.DELETE_SUCCEEDED,
                        null);
            }
        }
    }
    @GuardedBy("mPackages")
+27 −21
Original line number Diff line number Diff line
@@ -1619,6 +1619,12 @@ class PackageManagerShellCommand extends ShellCommand {
        }

        userId = translateUserId(userId, true /*allowAll*/, "runUninstall");
        final LocalIntentReceiver receiver = new LocalIntentReceiver();
        PackageManagerInternal internal = LocalServices.getService(PackageManagerInternal.class);

        if (internal.isApexPackage(packageName)) {
            internal.uninstallApex(packageName, versionCode, userId, receiver.getIntentSender());
        } else {
            if (userId == UserHandle.USER_ALL) {
                userId = UserHandle.USER_SYSTEM;
                flags |= PackageManager.DELETE_ALL_USERS;
@@ -1639,10 +1645,10 @@ class PackageManagerShellCommand extends ShellCommand {
                }
            }

        final LocalIntentReceiver receiver = new LocalIntentReceiver();
            mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
                            versionCode), null /*callerPackageName*/, flags,
                    receiver.getIntentSender(), userId);
        }

        final Intent result = receiver.getResult();
        final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,