国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

pms包管理服務分析-apk卸載流程

2019-11-09 17:27:01
字體:
來源:轉載
供稿:網友

apk的卸載流程相對比較簡單,總結大方向就兩步,一個是刪除安裝的文件和數據,另外一個是清除內存信息。另外要注意的是在多用戶模式下,apk的卸載刪除則不是單純的刪除文件。

下面來看看apk的卸載流程。

[/frameworks/base/core/java/android/app/applicationPackageManager.java]

    @Override    public void deletePackage(String packageName, ipackageDeleteObserver observer, int flags) {        try {            mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);        } catch (RemoteException e) {            // Should never happen!        }    }

Client端調用PackageManager的deletePackage方法刪除對應包名的apk,其中通過注冊IPackageDeleteObserver監聽卸載結果。實際上通過binder調用pms的deletePackageAsUser方法,在服務中執行卸載動作。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

@Overridepublic void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int userId,		int flags) {	deletePackage(packageName, new LegacyPackageDeleteObserver(observer).getBinder(), userId,			flags);}

@Override

public void deletePackage(final String packageName,

final IPackageDeleteObserver observer, final int userId, final int flags) {

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES, null);

if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {

try {

observer.onPackageDeleted(packageName,PackageManager.DELETE_FAILED_USER_RESTRICTED, null);

} catch (RemoteException re) {

}

return;

}

// 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

});

}

deletePackageAsUser調用delePackage方法,先校驗調用方是否有DELETE_PACKAGE權限,再檢查UserRestriction行為限制,都pass以后異步執行deletePackageX方法,最后將結果通過IpackageDeleteObserver返回。下面來看看deletePackageX方法的內容。

    PRivate int deletePackageX(String packageName, int userId, int flags) {        final PackageRemovedInfo info = new PackageRemovedInfo();        final boolean res;        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;        }        synchronized (mInstallLock) {            res = deletePackageLI(packageName, removeForUser,true, allUsers, perUserInstalled,                    flags | REMOVE_CHATTY, info, true);            systemUpdate = info.isRemovedPackageSystemUpdate;            if (res && !systemUpdate && mPackages.get(packageName) == null) {                removedForAllUsers = true;            }        }        // Force a gc here.        Runtime.getRuntime().gc();        if (info.args != null) {            synchronized (mInstallLock) {                info.args.doPostDeleteLI(true);            }        }        return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;    }

deletePackageX方法中首先創建PackageRemoveInfo實例,PackageRemoveInfo類結構如下圖,主要保存刪除應用的基本信息。

然后檢查刪除的應用是否已激活的DeviceManager,如果是則返回卸載失敗,要求先取消激活。

如果沒問題繼續執行deletePackageLI方法,傳入PackageRemoveInfo實例用于記錄卸載后應用的基本信息。

    private boolean deletePackageLI(String packageName, UserHandle user,            boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,            int flags, PackageRemovedInfo outInfo,            boolean writeSettings) {        if (packageName == null) {            Slog.w(TAG, "Attempt to delete null packageName.");            return false;        }        PackageSetting ps;        boolean dataOnly = false;        int removeUser = -1;        int appId = -1;        synchronized (mPackages) {            ps = mSettings.mPackages.get(packageName);        }        boolean ret = false;        if (isSystemApp(ps)) {            ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,flags, outInfo, writeSettings);        } else {            killApplication(packageName, ps.appId, "uninstall pkg");            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,                    allUserHandles, perUserInstalled,                    outInfo, writeSettings);        }        return ret;    }

針對系統應用的卸載我們暫時不跟,來跟下最普遍的第三方應用的卸載過程。在deletePackageLI方法中根據包名獲得對應的PackageSetting實例,首先調用killApplication方法殺死應用進程后執行deleteInstalledPackageLI方法刪除應用數據。

    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);        return true;    }

最后調用removePakcageDataLI方法。

    private void removePackageDataLI(PackageSetting ps, int[] allUserHandles, boolean[] perUserInstalled,            PackageRemovedInfo outInfo, int flags, boolean writeSettings) {        String packageName = ps.name;        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);        removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);        final PackageSetting deletedPs;        synchronized (mPackages) {            deletedPs = mSettings.mPackages.get(packageName);            if (outInfo != null) {                outInfo.removedPackage = packageName;                outInfo.removedUsers = deletedPs != null                        ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) : null;            }        }        if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {            removeDataDirsLI(ps.volumeUuid, packageName);            schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);        }        if (outInfo != null) {            // A user ID was deleted here. Go through all users and remove it            // from KeyStore.            removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);        }    }

removePakcageDataLI方法是重點,這里主要和開頭說的兩點,刪除內存數據,刪除安裝文件。

首先調用removePackageLI方法刪除應用的內存數據,主要有在mPackages總安裝應用列表中刪除對應實例,清除所有應用組件,如activity, provider, service, contentresolver, receiver, permissions等,方法內容如下:

    void removePackageLI(PackageSetting ps, boolean chatty) {        // writer        synchronized (mPackages) {            mPackages.remove(ps.name);            final PackageParser.Package pkg = ps.pkg;            if (pkg != null) {                cleanPackageDataStructuresLILPw(pkg, chatty);            }        }    }    void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {        int N = pkg.providers.size();        int i;        for (i=0; i<N; i++) {            PackageParser.Provider p = pkg.providers.get(i);            mProviders.removeProvider(p);	  }        N = pkg.services.size();        r = null;        for (i=0; i<N; i++) {            PackageParser.Service s = pkg.services.get(i);            mServices.removeService(s);        }        …}

然后調用removeDataDirsLI刪除應用的安裝和數據文件。

    private int removeDataDirsLI(String volumeUuid, String packageName) {        int[] users = sUserManager.getUserIds();        int res = 0;        for (int user : users) {            int resInner = mInstaller.remove(volumeUuid, packageName, user);            if (resInner < 0) {                res = resInner;            }        }        return res;    }

至此第三方應用的卸載過程如上所述,當然還有很多細節內容需要一點點的發散去學習。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 库车县| 青岛市| 牙克石市| 五华县| 南昌县| 安阳市| 庄浪县| 和平县| 郎溪县| 来凤县| 大同县| 南靖县| 靖宇县| 聊城市| 定西市| 雅江县| 自贡市| 会理县| 长治市| 分宜县| 彭阳县| 永泰县| 金沙县| 武功县| 龙岩市| 万安县| 海南省| 元谋县| 瓦房店市| 怀安县| 冀州市| 高台县| 阜阳市| 萍乡市| 平乐县| 章丘市| 安塞县| 翁牛特旗| 招远市| 西林县| 浮梁县|