Android apk卸载流程

卸载流程

 

4.1 卸载的调用堆栈

看看卸载的调用堆栈

05-01 08:50:27.174: D/PackageManagerService(1107): com.android.server.pm.PackageManagerService.deletePackage(PackageManagerService.java:14445)

05-01 08:50:27.174: D/PackageManagerService(1107): com.android.server.pm.PackageManagerService.deletePackageAsUser(PackageManagerService.java:14432)

05-01 08:50:27.174: D/PackageManagerService(1107): android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:1038)

05-01 08:50:27.174: D/PackageManagerService(1107): com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3144)

05-01 08:50:27.174: D/PackageManagerService(1107): android.os.Binder.execTransact(Binder.java:458)

 

在桌面进行卸载的时候,发送卸载命令给PMS

 

通过binder调用到PMSdeletePackageAsUser

接着调用deletePackage

deletePackage

       // Queue up an async operation since the package deletion may take a little while.

        mHandler.post(new Runnable() {

            public void run() {

                mHandler.removeCallbacks(this);

                final int returnCode = deletePackageX(packageName, userId, flags);

                if (observer != null) {

                    try {

                        observer.onPackageDeleted(packageName, returnCode, null);

                    } catch (RemoteException e) {

                        Log.i(TAG, "Observer no longer exists.");

                    } //end catch

                } //end if

            } //end run

        });

 

 

 

调到了deletePackageX

4.2 deletePackageX

    private int deletePackageX(String packageName, int userId, int flags) {

        final PackageRemovedInfo info = new PackageRemovedInfo();

        final boolean res;

 

        final UserHandle removeForUser = (flags & PackageManager.DELETE_ALL_USERS) != 0

                ? UserHandle.ALL : new UserHandle(userId);

 

        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {

            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");

            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;

        }

 

        boolean removedForAllUsers = false;

        boolean systemUpdate = false;

 

        // for the uninstall-updates case and restricted profiles, remember the per-

        // userhandle installed state

        int[] allUsers;

        boolean[] perUserInstalled;

        synchronized (mPackages) {

            PackageSetting ps = mSettings.mPackages.get(packageName);

            allUsers = sUserManager.getUserIds();

            perUserInstalled = new boolean[allUsers.length];

            for (int i = 0; i < allUsers.length; i++) {

                perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;

            }

        }

 

        synchronized (mInstallLock) {

            if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);

            res = deletePackageLI(packageName, removeForUser,

                    true, allUsers, perUserInstalled,

                    flags | REMOVE_CHATTY, info, true);

            systemUpdate = info.isRemovedPackageSystemUpdate;

            if (res && !systemUpdate && mPackages.get(packageName) == null) {

                removedForAllUsers = true;

            }

            if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate

                    + " removedForAllUsers=" + removedForAllUsers);

        }

 

        if (res) {

            info.sendBroadcast(true, systemUpdate, removedForAllUsers);

 

            // If the removed package was a system update, the old system package

            // was re-enabled; we need to broadcast this information

            if (systemUpdate) {

                Bundle extras = new Bundle(1);

                extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0

                        ? info.removedAppId : info.uid);

                extras.putBoolean(Intent.EXTRA_REPLACING, true);

                              

                String category = null;

                if (info.isThemeApk) {

                    category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE;

                }

 

                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, category,

                        extras, null, null, null);

                sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, category,

                        extras, null, null, null);

     

                             

            } else {

              

            }

        }

               

                                          

        // Force a gc here.

        Runtime.getRuntime().gc();

        // Delete the resources here after sending the broadcast to let

        // other processes clean up before deleting resources.

        if (info.args != null) {

            synchronized (mInstallLock) {

                info.args.doPostDeleteLI(true);

            }

        }

 

        return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;

    }

 

 

这里调用到了info.args.doPostDeleteLI(true);

由于info.args是抽象类InstallArgsstatic abstract class InstallArgs

卸载的是手机内部存储里的应用时,执行的是FileInstallArgs类的doPostDeleteLI方法

 

info.args是在这里得到的

    private boolean deleteInstalledPackageLI(PackageSetting ps,

            boolean deleteCodeAndResources, int flags,

            int[] allUserHandles, boolean[] perUserInstalled,

            PackageRemovedInfo outInfo, boolean writeSettings) {

        if (outInfo != null) {

            outInfo.uid = ps.appId;

        }

 

        // Delete package data from internal structures and also remove data if flag is set

        removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);

 

        // Delete application code and resources

        if (deleteCodeAndResources && (outInfo != null)) {

            outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),

                    ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));

            if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);

        }

        return true;

    }

 

 

createInstallArgsForExisting

   /**

     * Create args that describe an existing installed package. Typically used

     * when cleaning up old installs, or used as a move source.

     */

    private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,

            String resourcePath, String[] instructionSets) {

        final boolean isInAsec;

        if (installOnExternalAsec(installFlags)) {

            /* Apps on SD card are always in ASEC containers. */

            isInAsec = true;

        } else if (installForwardLocked(installFlags)

                && !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {

            /*

             * Forward-locked apps are only in ASEC containers if they're the

             * new style

             */

            isInAsec = true;

        } else {

            isInAsec = false;

        }

 

        if (isInAsec) {

            return new AsecInstallArgs(codePath, instructionSets,

                    installOnExternalAsec(installFlags), installForwardLocked(installFlags));

        } else {

            return new FileInstallArgs(codePath, resourcePath, instructionSets);

        }

    }

 

 

4.3 SD卡里应用的卸载

卸载SD卡里的应用时,执行到了AsecInstallArgs类的

        boolean doPostDeleteLI(boolean delete) {

            if (DEBUG_SD_INSTALL) Slog.i(TAG, "doPostDeleteLI() del=" + delete);

            final List<String> allCodePaths = getAllCodePaths();

            boolean mounted = PackageHelper.isContainerMounted(cid);

            if (mounted) {

                // Unmount first

                if (PackageHelper.unMountSdDir(cid)) {

                    mounted = false;

                }

            }

            if (!mounted && delete) {

                cleanUpResourcesLI(allCodePaths);

            }

            return !mounted;

        }

 

if (PackageHelper.unMountSdDir(cid)) 里,调用到MountService.java里的

    public int unmountSecureContainer(String id, boolean force) {

        Slog.i(TAG, "unmountSecureContainer, id=" + id

                + ", force=" + force);

        enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);

        waitForReady();

        warnOnNotMounted();

 

        synchronized (mAsecMountSet) {

            if (!mAsecMountSet.contains(id)) {

                Slog.i(TAG, "OperationFailedStorageNotMounted");

                return StorageResultCode.OperationFailedStorageNotMounted;

            }

         }

 

        /*

         * Force a GC to make sure AssetManagers in other threads of the

         * system_server are cleaned up. We have to do this since AssetManager

         * instances are kept as a WeakReference and it's possible we have files

         * open on the external storage.

         */

        Runtime.getRuntime().gc();

        System.runFinalization();

 

        int rc = StorageResultCode.OperationSucceeded;

        try {

            final Command cmd = new Command("asec", "unmount", id);

            if (force) {

                cmd.appendArg("force");

            }

            mConnector.execute(cmd);

        } catch (NativeDaemonConnectorException e) {

            int code = e.getCode();

            if (code == VoldResponseCode.OpFailedStorageBusy) {

                rc = StorageResultCode.OperationFailedStorageBusy;

            } else {

                rc = StorageResultCode.OperationFailedInternalError;

            }

        }

 

        if (rc == StorageResultCode.OperationSucceeded) {

            synchronized (mAsecMountSet) {

                mAsecMountSet.remove(id);

            }

        }

        return rc;

    }

 

    public boolean isSecureContainerMounted(String id) {

        enforcePermission(android.Manifest.permission.ASEC_ACCESS);

        waitForReady();

        warnOnNotMounted();

 

        synchronized (mAsecMountSet) {

            return mAsecMountSet.contains(id);

        }

    }

 

    public int renameSecureContainer(String oldId, String newId) {

        Slog.i(TAG, "renameSecureContainer, oldId=" + oldId

                + ", newId=" + newId);

        enforcePermission(android.Manifest.permission.ASEC_RENAME);

        waitForReady();

        warnOnNotMounted();

 

        synchronized (mAsecMountSet) {

            /*

             * Because a mounted container has active internal state which cannot be

             * changed while active, we must ensure both ids are not currently mounted.

             */

            if (mAsecMountSet.contains(oldId) || mAsecMountSet.contains(newId)) {

                return StorageResultCode.OperationFailedStorageMounted;

            }

        }

 

        int rc = StorageResultCode.OperationSucceeded;

        try {

            mConnector.execute("asec", "rename", oldId, newId);

        } catch (NativeDaemonConnectorException e) {

            rc = StorageResultCode.OperationFailedInternalError;

        }

 

        return rc;

    }

 

vold进程进行通信

发送类似SND -> {35 asec unmount com.dannyAndroid.stuinfo-2 force}的指令

vold进行umount操作

vold在处理的时候,发现base.apk被占用,就向system_server发送了kill信号,导致重启,见1.1

 

05-01 09:33:54.881: D/VoldConnector(1107): SND -> {33 asec unmount com.UCMobile-2 force}

system_server调到pid 385

 

05-01 09:33:54.881: D/FrameworkListener(385): dispatchCommand data = (33 asec unmount com.UCMobile-2 force)

05-01 09:33:54.881: D/VoldCmdListener(385): asec unmount com.UCMobile-2 force

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值