Refactor and rename onPackageStateRemoved() to onPackageUninstalled().
Under what conditions to notify the permission subsystem that a package is considered uninstalled can be tricky/confusing, because there are so many different code paths and flavors for deleting a package, deleting a package can mean different things, and it's critical to get it right for permissions due to security concerns. If a package is being deleted as a upgrade step, we should not consider it an uninstallation (but a later package installation with replaced == true), and handle the <uses-permission> change later in that callback. This is also true for uninstalling an updated system package and reinstalling the factory version later, but that's a different code path. For system packages, we normally can't just completely remove their permission state upon uninstallation, because they can be marked as installed later, and permission pregrants needs to stick for them. So in this case we just clear the user modifiable permission state instead of dropping the whole state. However, we cannot assume that we should never drop the permission state for a system package, because there are package uninstallations during the package reconciliation phase of system boot that we do need to remove the permission state for invalid (e.g. missing) system packages. DELETE_KEEP_DATA as a flag for deleting a package actually means two different things when marking package as uninstalled v.s. removing package for all users. When marking a package as uninstalled, this flag only affects whether the data directory is deleted (as what is described in its javadoc), and all other states (including permission state) is always deleted because it's an uninstallation for that user. However when removing a package for all users, specifying this flag actually means keeping all package states and only remove the APK, which is also used when an external SD card is ejected (or a package is upgraded, or uninstalling an updated system package which has a lower version than its factory version due to OTA). In other words, uninstalling a package for all users with DELETE_KEEP_DATA actually keeps the package installed and all its states (including PackageSetting) intact, so it shouldn't be considred uninstalled for permission; whereas uninstalling for a subset of users with DELETE_KEEP_DATA marks the package uninstalled and removes most package state for those users except for the data directory, so it should be considered uninstalled for permission. Another subtle aspect of DELETE_KEEP_DATA is that it is always set when deleting an updated system app whose version is lower than its factory version due to OTA, but never set when the factory version is older, i.e. a downgrade, which is more often the case. In this case we are deleting most of the package states, however we do need to keep the permission state mostly intact, as to user it's only a replacement so user preference should be carried over, and the downgraded app cannot be missing pregranted permissions anyway. So the current implementation is that we need to clear the no longer requested permission states if the app has a shared user ID, or leave it as-is if it doesn't as permissions not requested won't be reported as granted. According to the discussion above, we are no longer calling the onPackageUninstalled() callback when a updated system package is being uninstalled for later installation of its factory version, because it should be considered as a package replacement instead of an uninstallation that should remove/reset its permission state. This is covered by the call to updatePermissions() inside installPackageFromSystemLIF() called by deleteSystemPackageLIF(), which is also moved a bit later to allow correct installed state to be set first. The method updatePermissions() should be later refactored into onPackageInstalled(). The call to updatePermissions() in the old onPackageStateRemoved() is actually necessary because it removes permission definitions according. On the contrary, removeAllPermissions() called in onPackageRemoved() only removes the PermissionInfo object in Permission, instead of the Permission itself, because it may be called upon SD card ejection. Bug: 158736025 Test: presubmit Change-Id: I06321ba21ee9e13a9bfbb1c990bbd50a68503b88
Loading
Please register or sign in to comment