Skip to content
Commit ea789fd6 authored by Hai Zhang's avatar Hai Zhang
Browse files

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
parent 6b086884
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment