Loading core/java/android/content/pm/PackageManagerInternal.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } services/core/java/com/android/server/pm/ApexManager.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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. * Loading services/core/java/com/android/server/pm/PackageManagerService.java +44 −0 Original line number Diff line number Diff line Loading @@ -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") services/core/java/com/android/server/pm/PackageManagerShellCommand.java +27 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading Loading
core/java/android/content/pm/PackageManagerInternal.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); }
services/core/java/com/android/server/pm/ApexManager.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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. * Loading
services/core/java/com/android/server/pm/PackageManagerService.java +44 −0 Original line number Diff line number Diff line Loading @@ -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")
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +27 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading