privateintrunUninstall()throws RemoteException { final PrintWriter pw = getOutPrintWriter(); int flags = 0; int userId = UserHandle.USER_ALL; long versionCode = PackageManager.VERSION_CODE_HIGHEST;
final String packageName = getNextArg(); if (packageName == null) { pw.println("Error: package name not specified"); return1; }
/ if a split is specified, just remove it and not the whole package ArrayList<String> splitNames = getRemainingArgs(); if (!splitNames.isEmpty()) { return runRemoveSplits(packageName, splitNames); } // 不加--user是卸载所有用户的应用 if (userId == UserHandle.USER_ALL) { flags |= PackageManager.DELETE_ALL_USERS; } finalint translatedUserId = translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall"); final LocalIntentReceiver receiver = new LocalIntentReceiver(); final PackageManagerInternal internal = LocalServices.getService(PackageManagerInternal.class);
if (internal.isApexPackage(packageName)) { internal.uninstallApex( packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags); } else { //如果删除某一个用户的应用,走这里 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) { final PackageInfo info = mInterface.getPackageInfo(packageName, PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, translatedUserId); if (info == null) { pw.println("Failure [not installed for " + translatedUserId + "]"); return1; } finalboolean isSystem = (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; // If we are being asked to delete a system app for just one // user set flag so it disables rather than reverting to system // version of the app. if (isSystem) { flags |= PackageManager.DELETE_SYSTEM_APP; } } mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName, versionCode), null/*callerPackageName*/, flags, receiver.getIntentSender(), translatedUserId); }
final Intent result = receiver.getResult(); finalint status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); if (status == PackageInstaller.STATUS_SUCCESS) { pw.println("Success"); return0; } else { pw.println("Failure [" + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); return1; } }
/** * Uninstall the given package with a specific version code, removing it * completely from the device. If the version code of the package * does not match the one passed in the versioned package argument this * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to * uninstall the latest version of the package. * <p> * This method is available to: * <ul> * <li>the current "installer of record" for the package * <li>the device owner * <li>the affiliated profile owner * </ul> * * @param versionedPackage The versioned package to uninstall. * @param statusReceiver Where to deliver the result. * * @see android.app.admin.DevicePolicyManager */ @RequiresPermission(anyOf = { Manifest.permission.DELETE_PACKAGES, Manifest.permission.REQUEST_DELETE_PACKAGES}) publicvoiduninstall(@NonNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver){ uninstall(versionedPackage, 0/*flags*/, statusReceiver); }
/** * Uninstall the given package with a specific version code, removing it * completely from the device. This method is only available to the current * "installer of record" for the package. If the version code of the package * does not match the one passed in the versioned package argument this * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to * uninstall the latest version of the package. * * @param versionedPackage The versioned package to uninstall. * @param flags Flags for uninstall. * @param statusReceiver Where to deliver the result. * * @hide */ @RequiresPermission(anyOf = { Manifest.permission.DELETE_PACKAGES, Manifest.permission.REQUEST_DELETE_PACKAGES}) publicvoiduninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlagsint flags, @NonNull IntentSender statusReceiver){ Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null"); try { //binder调用 mInstaller.uninstall(versionedPackage, mInstallerPackageName, flags, statusReceiver, mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
@Override publicvoiduninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, IntentSender statusReceiver, int userId){ final Computer snapshot = mPm.snapshotComputer(); finalint callingUid = Binder.getCallingUid(); snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) { mAppOps.checkPackage(callingUid, callerPackageName); }
// Check whether the caller is device owner or affiliated profile owner, in which case we do // it silently. DevicePolicyManagerInternal dpmi = LocalServices.getService(DevicePolicyManagerInternal.class); finalboolean canSilentlyInstallPackage = dpmi != null && dpmi.canSilentlyInstallPackage(callerPackageName, callingUid);
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, versionedPackage.getPackageName(), canSilentlyInstallPackage, userId); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) { // Sweet, call straight through! mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); } elseif (canSilentlyInstallPackage) { // Allow the device owner and affiliated profile owner to silently delete packages // Need to clear the calling identity to get DELETE_PACKAGES permission finallong ident = Binder.clearCallingIdentity(); try { mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); } finally { Binder.restoreCallingIdentity(ident); } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.UNINSTALL_PACKAGE) .setAdmin(callerPackageName) .write(); } else { ApplicationInfo appInfo = snapshot.getApplicationInfo(callerPackageName, 0, userId); if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES, null); }
// Take a short detour to confirm with user final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null)); intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder()); adapter.onUserActionRequired(intent); } }
com/android/server/pm/IPackageManagerBase.java
1 2 3 4 5 6 7 8
@Override @Deprecated publicfinalvoiddeletePackageAsUser(String packageName, int versionCode, IPackageDeleteObserver observer, int userId, int flags){ deletePackageVersioned(new VersionedPackage(packageName, versionCode), new PackageManager.LegacyPackageDeleteObserver(observer).getBinder(), userId, flags); }