应用卸载的流程梳理

在设置界面点卸载按钮执行如下代码

 public static final String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";

 void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) {

        Uri packageUri = Uri.parse("package:" + packageName);
        Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
        uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers);
        mFragment.startActivityForResult(uninstallIntent, requestUninstallCode);
     
    }

跳转到PackageInstaller应用卸载界面:

\PackageInstaller\src\com\android\packageinstaller\UninstallUninstalling.java

  @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

                //****省略代码

                // 弹出确认是否需要卸载的提示框UninstallUninstallingFragment:
        
                DialogFragment dialog = new UninstallUninstallingFragment();
                dialog.setCancelable(false);
                dialog.show(transaction, "dialog");

              //注册等待卸载完成的广播和回调
                mUninstallId = UninstallEventReceiver.addObserver(this,
                        EventResultPersister.GENERATE_NEW_ID, this);

                Intent broadcastIntent = new Intent(BROADCAST_ACTION);
                broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mUninstallId);
                broadcastIntent.setPackage(getPackageName());

                PendingIntent pendingIntent = PendingIntent.getBroadcast(this, mUninstallId,
                        broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT
                                | PendingIntent.FLAG_MUTABLE);

                int flags = allUsers ? PackageManager.DELETE_ALL_USERS : 0;
                flags |= keepData ? PackageManager.DELETE_KEEP_DATA : 0;

                try {
                  //开始卸载
                      ActivityThread.getPackageManager().getPackageInstaller().uninstall(
                            new VersionedPackage(mAppInfo.packageName,
                                    PackageManager.VERSION_CODE_HIGHEST),
                            getPackageName(), flags, pendingIntent.getIntentSender(),
                            user.getIdentifier());

              //****省略代码
            
        }
    }

通过IPackageInstaller.java这个接口实现跨进程通信,此时的客户端为PackageInstaller.apk,服务端为 PackageInstallerService.java,就直接调用到PackageInstallerService.java中的uninstall方法中去了。代码如下:

frameworks\base\core\java\android\content\pm\PackageInstaller.java

 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags,
            @NonNull IntentSender statusReceiver) {
        Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null");
        try {
            mInstaller.uninstall(versionedPackage, mInstallerPackageName,
                    flags, statusReceiver, mUserId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

frameworks\base\services\core\java\com\android\server\pm\PackageInstallerService.java

// frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
 @Override
    public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,
                IntentSender statusReceiver, int userId) {
        // 先获取 UID
        final int callingUid = Binder.getCallingUid();
        // 检查执行权限
        mPermissionManager.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
        //创建PackageDeleteObserverAdapter对象,用于接收响应删除的结果
        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 
            mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
        ......
}

这个方法主要做了3件事情:

  1. 创建PackageDeleteObserverAdapter对象,用于接收响应删除的结果;

  2. 检查当前程序是否具有删除权限,如果有的话,就调用 mPm.deletePackageVersioned方法;

  3. 调用PMS的deletePackageVersioned()方法执行程序的卸载。

  4. 最后卸载调用了mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); 所以走到了PackageManagerService的deletePackageVersioned()。

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

@Override
    public void deletePackageVersioned(VersionedPackage versionedPackage,
            final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
        deletePackageVersionedInternal(versionedPackage, observer, userId, deleteFlags, false);
    }

deletePackageVersioned调用了deletePackageVersionedInternal(versionedPackage, observer, userId, deleteFlags, false);

 private void deletePackageVersionedInternal(VersionedPackage versionedPackage,
            final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags,
            final boolean allowSilentUninstall) {

//********省略代码
mHandler.post(() -> {
            int returnCode;
            final PackageSetting ps =     mSettings.mPackages.get(internalPackageName);
            boolean doDeletePackage = true;
            if (ps != null) {
                final boolean targetIsInstantApp =
                        ps.getInstantApp(UserHandle.getUserId(callingUid));
                doDeletePackage = !targetIsInstantApp
                        || canViewInstantApps;
            }
            if (doDeletePackage) {
                if (!deleteAllUsers) {
                    //走这里的逻辑
                    returnCode = deletePackageX(internalPackageName, versionCode,
                            userId, deleteFlags);
                } else {

            try {
                //删除apk后的回调方法
                observer.onPackageDeleted(packageName, returnCode, null);
            } catch (RemoteException e) {
                Log.i(TAG, "Observer no longer exists.");
            } //end catch
        
     
    }

在deletePackageVersionedInternal()中发送Post事件执行异步删除操作,在Handler事件中调用deletePackageX()方法。

// PackageManagerService.java
int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags) {
       ....

       if (isPackageDeviceAdmin(packageName, removeUser)) {
            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
        }

        synchronized (mInstallLock) {
            if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
            try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
                    deleteFlags, "deletePackageX")) {
                //调用这个方法
                res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
                        deleteFlags | PackageManager.DELETE_CHATTY, info, true, null);
            }
        ....
}

在deletePackageX()中首先判断要卸载的程序是否是admin管理的,如果是则直接return;如果不是则执行deletePackageLIF()方法继续卸载程序。

// PackageManagerService.java
private boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
            boolean deleteCodeAndResources, int[] allUserHandles, int flags,
            PackageRemovedInfo outInfo, boolean writeSettings,
            PackageParser.Package replacingPackage) {
    .....
    try {
            // 继续调用卸载方法
            executeDeletePackageLIF(action, packageName, deleteCodeAndResources,
                    allUserHandles, writeSettings, replacingPackage);
        } catch (SystemDeleteException e) {
            if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: system deletion failure", e);
            return false;
        }
    .....
}

执行到executeDeletePackageLIF方法中

// PackageManagerService.java
    private void executeDeletePackageLIF(DeletePackageAction action,
            String packageName, boolean deleteCodeAndResources,
            int[] allUserHandles, boolean writeSettings,
            PackageParser.Package replacingPackage) throws SystemDeleteException {
        ......
        //是否是系统app
        final boolean systemApp = isSystemApp(ps);

        ......
        // TODO(b/109941548): break reasons for ret = false out into mayDelete method
        if (systemApp) {
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
            // When an updated system application is deleted we delete the existing resources
            // as well and fall back to existing code in system partition
            deleteSystemPackageLIF(action, ps, allUserHandles, flags, outInfo, writeSettings);
        } else {
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
            // 这里卸载的是三方应用
            deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
                    outInfo, writeSettings, replacingPackage);
        }
        ......
    }

在executeDeletePackageLIF函数中根据是否是systemApp调用不同的流程,如果是systemApp,则调用deleteSystemPackageLIF完成卸载;如果非systemApp,则调用deleteInstalledPackageLIF完成卸载,当然在卸载之前,首先会调用AMS的killApplication方法先让这个APP停止运行,deleteInstalledPackageLIF 方法。

// PackageManagerService.java
    private void deleteInstalledPackageLIF(PackageSetting ps,
            boolean deleteCodeAndResources, int flags, int[] allUserHandles,
            PackageRemovedInfo outInfo, boolean writeSettings,
            PackageParser.Package replacingPackage) {

        ......
        // Delete package data from internal structures and also remove data if flag is set
        //从内部结构中删除包数据,如果设置了标志,也删除数据
        removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings);
        ......
    }

removePackageDataLIF()方法

 private void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
            PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
        String packageName = deletedPs.name;
        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
        // Retrieve object to delete permissions for shared user later on
        // 检索对象以稍后删除共享用户的权限
        final AndroidPackage deletedPkg = deletedPs.pkg;
        
        //*******省略代码
       //删除数据
        removePackageLI(deletedPs.name, (flags & PackageManager.DELETE_CHATTY) != 0);

        if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
            final AndroidPackage resolvedPkg;
          
              //*******省略代码

             //注释2:删除目录和配置文件
            destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
                    FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
            destroyAppProfilesLIF(resolvedPkg);
            if (outInfo != null) {
                outInfo.dataRemoved = true;
            }
        }

        int removedAppId = -1;

        // writer
        boolean installedStateChanged = false;
        if (deletedPs != null) {
            if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
                final SparseBooleanArray changedUsers = new SparseBooleanArray();
                synchronized (mLock) {
                    mDomainVerificationManager.clearPackage(deletedPs.name);
                //移除mSetting中保存的数据                    
                mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
                    mAppsFilter.removePackage(getPackageSetting(packageName));
                    removedAppId = mSettings.removePackageLPw(packageName);
                    if (outInfo != null) {
                        outInfo.removedAppId = removedAppId;
                    }
                    if (!mSettings.isDisabledSystemPackageLPr(packageName)) {
                        // If we don't have a disabled system package to reinstall, the package is
                        // really gone and its permission state should be removed.
                        final SharedUserSetting sus = deletedPs.getSharedUser();
                        List<AndroidPackage> sharedUserPkgs = sus != null ? sus.getPackages()
                                : null;
                        if (sharedUserPkgs == null) {
                            sharedUserPkgs = Collections.emptyList();
                        }
                        //通知PermissionManagerService卸载,更新权限信息
                        mPermissionManager.onPackageUninstalled(packageName, deletedPs.appId,
                                deletedPs.pkg, sharedUserPkgs, UserHandle.USER_ALL);
                    }
                   //清除设置数据
                     clearPackagePreferredActivitiesLPw(
                            deletedPs.name, changedUsers, UserHandle.USER_ALL);
                }
                if (changedUsers.size() > 0) {
                    updateDefaultHomeNotLocked(changedUsers);
                    postPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
                }
            }
            // make sure to preserve per-user disabled state if this removal was just
            // a downgrade of a system app to the factory package
            if (outInfo != null && outInfo.origUsers != null) {
                if (DEBUG_REMOVE) {
                    Slog.d(TAG, "Propagating install state across downgrade");
                }
                for (int userId : allUserHandles) {
                    final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId);
                    if (DEBUG_REMOVE) {
                        Slog.d(TAG, "    user " + userId + " => " + installed);
                    }
                    if (installed != deletedPs.getInstalled(userId)) {
                        installedStateChanged = true;
                    }
                    deletedPs.setInstalled(installed, userId);
                    if (installed) {
                        deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
                    }
                }
            }
        }
        synchronized (mLock) {
            // can downgrade to reader
            if (writeSettings) {
                // Save settings now
                writeSettingsLPrTEMP();
            }
            if (installedStateChanged) {
                mSettings.writeKernelMappingLPr(deletedPs);
            }
        }
        if (removedAppId != -1) {
            // A user ID was deleted here. Go through all users and remove it
            // from KeyStore.
             //此处删除了用户ID。浏览所有用户并将其从KeyStore中删除            
            removeKeystoreDataIfNeeded(
                    mInjector.getUserManagerInternal(), UserHandle.USER_ALL, removedAppId);
        }
    }

removePackageDataLIF用于删除应用的/data/data数据目录,并且从PMS内部数据结构里面清除package的信息。首先调用removePackageLI从PMS内部的数据结构上删除要卸载的package信息。

removePackageLI方法如下:

    private void removePackageLI(AndroidPackage pkg, boolean chatty) {
        // Remove the parent package setting
        PackageSetting ps = getPackageSetting(pkg.getPackageName());
        if (ps != null) {
            removePackageLI(ps.name, chatty);
        } else if (DEBUG_REMOVE && chatty) {
            Log.d(TAG, "Not removing package " + pkg.getPackageName() + "; mExtras == null");
        }
    }

    private void removePackageLI(String packageName, boolean chatty) {
        if (DEBUG_INSTALL) {
            if (chatty)
                Log.d(TAG, "Removing package " + packageName);
        }

        // writer
        synchronized (mLock) {
            final AndroidPackage removedPackage = mPackages.remove(packageName);
            if (removedPackage != null) {
                 //调用这个方法,删除四大组件相关的信息               
                 cleanPackageDataStructuresLILPw(removedPackage, chatty);
            }
        }
    }

cleanPackageDataStructuresLILPw用于将package的providers、services、receivers、activities等信息去PMS的全局数据结构上移除,cleanPackageDataStructuresLILPw如下 :

 private void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
       //移除所有组件 
        mComponentResolver.removeAllComponents(pkg, chatty);
        mPermissionManager.onPackageRemoved(pkg);
        mPackageProperty.removeAllProperties(pkg);

        //*****省略代码
    }

移除所有组件:

frameworks\base\services\core\java\com\android\server\pm\ComponentResolver.java

void removeAllComponents(AndroidPackage pkg, boolean chatty) {
        synchronized (mLock) {
            removeAllComponentsLocked(pkg, chatty);
            onChanged();
        }
    }

 private void removeAllComponentsLocked(AndroidPackage pkg, boolean chatty) {
        int componentSize;
        StringBuilder r;
        int i;

        componentSize = ArrayUtils.size(pkg.getActivities());
        r = null;
        for (i = 0; i < componentSize; i++) {
            ParsedActivity a = pkg.getActivities().get(i);
          //移除activity:
              mActivities.removeActivity(a, "activity");
           //*****省略代码
        }
          //*****省略代码

        componentSize = ArrayUtils.size(pkg.getProviders());
        r = null;
        for (i = 0; i < componentSize; i++) {
            ParsedProvider p = pkg.getProviders().get(i);
            mProviders.removeProvider(p); //移除Providers:
            //*****省略代码
        }

        //*****省略代码

        componentSize = ArrayUtils.size(pkg.getReceivers());
        r = null;
        for (i = 0; i < componentSize; i++) {
            ParsedActivity a = pkg.getReceivers().get(i);
            mReceivers.removeActivity(a, "receiver"); //移除receiver:
             //*****省略代码
        }

         //*****省略代码

        componentSize = ArrayUtils.size(pkg.getServices());
        r = null;
        for (i = 0; i < componentSize; i++) {
            ParsedService s = pkg.getServices().get(i);
            mServices.removeService(s); //移除Services
           
        }
        //*****省略代码
    }

在以上removeAllComponentsLocked方法中移除四大组件。

再回到removePackageDataLIF中的调用destroyAppDataLIF和destroyAppProfilesLIF去删除/data/data下面的目录

destroyAppDataLIF方法如下:

  private void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        destroyAppDataLeafLIF(pkg, userId, flags);
    }

    private void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.getPackageLPr(pkg.getPackageName());
        }
        for (int realUserId : resolveUserIds(userId)) {
            final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
            try {
            //跳转到Installer.java               
             mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
                        flags, ceDataInode);
            } catch (InstallerException e) {
                Slog.w(TAG, String.valueOf(e));
            }
            mDexManager.notifyPackageDataDestroyed(pkg.getPackageName(), userId);
        }
    }

通过mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId, flags, ceDataInode)方法跳转到Installer.java

// frameworks/base/services/core/java/com/android/server/pm/Installer.java
    public void destroyAppData(String uuid, String packageName, int userId, int flags,
            long ceDataInode) throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            // 执行守护进程Installd的方法
            mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }

然后在Installd守护进程执行删除app数据的动作,具体文件和方法:

跨进程调用InstalldNativeService.cpp的destroyAppData方法。

// frameworks/native/cmds/installd/InstalldNativeService.cpp 
binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid,
        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_UUID(uuid);
    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    const char* pkgname = packageName.c_str();

    binder::Status res = ok();
    if (flags & FLAG_STORAGE_CE) {
        // 构造/data/data/packageName的文件路径名
        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
        // 删除文件内容以及目录(比如Android/data/包名/
        if (delete_dir_contents_and_dir(path) != 0) {
            res = error("Failed to delete " + path);
        }
    }
    if (flags & FLAG_STORAGE_DE) {
        auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
        if (delete_dir_contents_and_dir(path) != 0) {
            res = error("Failed to delete " + path);
        }
        destroy_app_current_profiles(packageName, userId);
        // TODO(calin): If the package is still installed by other users it's probably
        // beneficial to keep the reference profile around.
        // Verify if it's ok to do that.
        destroy_app_reference_profile(packageName);
    }
    if (flags & FLAG_STORAGE_EXTERNAL) {
        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
        for (const auto& n : mStorageMounts) {
            auto extPath = n.second;
            if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
                extPath += StringPrintf("/%d", userId);
            } else if (userId != 0) {
                // TODO: support devices mounted under secondary users
                continue;
            }
            auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
            if (delete_dir_contents_and_dir(path, true) != 0) {
                res = error("Failed to delete contents of " + path);
            }
            path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
            if (delete_dir_contents_and_dir(path, true) != 0) {
                res = error("Failed to delete contents of " + path);
            }
            path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
            if (delete_dir_contents_and_dir(path, true) != 0) {
                res = error("Failed to delete contents of " + path);
            }
        }
    }
    return res;
}
  • create_data_user_ce_package_path方法构造/data/data/packageName的文件路径名,然后调用delete_dir_contents_and_dir来删除文件内容以及目录(比如Android/data/包名/;

  • Android/media/包名,Android/obb/包名/ 路径下的文件),前面介绍过,/data/data/packageName的文件其实都是符号链接,所以delete_dir_contents_and_dir的实现中都是调用unlinkat去删除这些符号链接;

到此应用程序的app安装文件和使用中产生的数据文件都已被删除,且配置文件已更新完成,此时会回调deletePackageVersioned()中的observer.onPackageDeleted(packageName, returnCode, null) 方法通知删除结果,这里回调的是PackageDeleteObserverAdapter类中(PackageInstallerService的内部类):

//frameworks\base\services\core\java\com\android\server\pm\PackageInstallerService.java
 
static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
        private final Context mContext;
        private final IntentSender mTarget;
        private final String mPackageName;
        private final Notification mNotification;

        public PackageDeleteObserverAdapter(Context context, IntentSender target,
                String packageName, boolean showNotification, int userId) {
            mContext = context;
            mTarget = target;
            mPackageName = packageName;
            //发送通知           
             if (showNotification) {
                mNotification = buildSuccessNotification(mContext,
                        mContext.getResources().getString(R.string.package_deleted_device_owner),
                        packageName,
                        userId);
            } else {
                mNotification = null;
            }
        }

        @Override
        public void onUserActionRequired(Intent intent) {
            //***省略代码
        }

        @Override
        public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
            if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null) {
                NotificationManager notificationManager = (NotificationManager)
                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.notify(basePackageName,
                        SystemMessage.NOTE_PACKAGE_STATE,
                        mNotification);
            }
            if (mTarget == null) {
                return;
            }
            final Intent fillIn = new Intent();
            fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
            fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                    PackageManager.deleteStatusToPublicStatus(returnCode));
            fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
                    PackageManager.deleteStatusToString(returnCode, msg));
            fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
            try {
            // 通知IntentSender对象接收删除结果              
              mTarget.sendIntent(mContext, 0, fillIn, null, null);
            } catch (SendIntentException ignored) {
            }
        }
    }

在onPackageDeleted()中,首先调用NotificationManager中方法发送notify()通知卸载成功,然后创建Intent对象并回调mTarget.sendIntent(),这里的mTarget对象其实就是卸载最开始时调用uninstall()方法传入的第二个参数,即IntentSender对象,用于接收删除的结果,并发送给在(PackageInstaller\src\com\android\packageinstaller\UninstallUninstalling.java)时已经注册好了的广播UninstallEventReceiver.java

等待卸载完成的广播:

PackageInstaller\src\com\android\packageinstaller\UninstallEventReceiver.java

 @Override
    public void onReceive(Context context, Intent intent) {
        getReceiver(context).onEventReceived(context, intent);
    }

  @NonNull private static EventResultPersister getReceiver(@NonNull Context context) {
        synchronized (sLock) {
            if (sReceiver == null) {
                sReceiver = new EventResultPersister(
                        TemporaryFileManager.getUninstallStateFile(context));
            }
        }

        return sReceiver;
    }

  void onEventReceived(@NonNull Context context, @NonNull Intent intent) {
       
            //省略代码*****

            if (observerToCall != null) {
                observerToCall.onResult(status, legacyStatus, statusMessage);
            } else {
                mResults.put(id, new EventResult(status, legacyStatus, statusMessage));
                writeState();
            }
        }
    }

然后再回到收到onResult后关闭界面

\PackageInstaller\src\com\android\packageinstaller\UninstallUninstalling.java

@Override
    public void onResult(int status, int legacyStatus, @Nullable String message) {
    //***省略代码

        finish();
    }

时序图:

应用层时序图:

系统层时序图:

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值