Update deletion conditions for a package's UsageStats.

If a profile owner is defined for a specific user, do not delete usage
stats for a package on package deletion.

Bug: 197399948
Test: atest UserUsageStatsServiceTest
Test: atest UsageStatsTest [all]
Change-Id: I94a8e3dfca8ef4c7616f77944d61726e06043b85
This commit is contained in:
Varun Shah
2021-10-20 09:24:41 -07:00
parent 6022de3616
commit 9af940970d
5 changed files with 43 additions and 10 deletions

View File

@@ -16,6 +16,7 @@
package android.app.admin;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
@@ -76,6 +77,13 @@ public abstract class DevicePolicyManagerInternal {
public abstract void addOnCrossProfileWidgetProvidersChangeListener(
OnCrossProfileWidgetProvidersChangeListener listener);
/**
* @param userHandle the handle of the user whose profile owner is being fetched.
* @return the configured supervision app if it exists and is the device owner or policy owner.
*/
public abstract @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
@NonNull UserHandle userHandle);
/**
* Checks if an app with given uid is an active device owner of its user.
*

View File

@@ -12746,6 +12746,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
@Override
public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
@NonNull UserHandle userHandle) {
return DevicePolicyManagerService.this.getProfileOwnerOrDeviceOwnerSupervisionComponent(
userHandle);
}
@Override
public boolean isActiveDeviceOwner(int uid) {
return isDeviceOwner(new CallerIdentity(uid, null, null));

View File

@@ -83,7 +83,7 @@ public class UserUsageStatsServiceTest {
HashMap<String, Long> installedPkgs = new HashMap<>();
installedPkgs.put(TEST_PACKAGE_NAME, System.currentTimeMillis());
mService.init(System.currentTimeMillis(), installedPkgs);
mService.init(System.currentTimeMillis(), installedPkgs, true);
}
@After

View File

@@ -403,6 +403,7 @@ public class UsageStatsService extends SystemService implements
if (userId == UserHandle.USER_SYSTEM) {
UsageStatsIdleService.scheduleUpdateMappingsJob(getContext());
}
final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId));
synchronized (mLock) {
// This should be safe to add this early. Other than reportEventOrAddToQueue and
// getBackupPayload, every other user grabs the lock before accessing
@@ -425,7 +426,7 @@ public class UsageStatsService extends SystemService implements
boolean needToFlush = !pendingEvents.isEmpty();
initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(),
installedPackages);
installedPackages, deleteObsoleteData);
final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId);
if (userService == null) {
Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
@@ -651,13 +652,13 @@ public class UsageStatsService extends SystemService implements
* when the user is initially unlocked.
*/
private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis,
HashMap<String, Long> installedPackages) {
HashMap<String, Long> installedPackages, boolean deleteObsoleteData) {
final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId),
"usagestats");
final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId,
usageStatsDir, this);
try {
service.init(currentTimeMillis, installedPackages);
service.init(currentTimeMillis, installedPackages, deleteObsoleteData);
mUserState.put(userId, service);
} catch (Exception e) {
if (mUserManager.isUserUnlocked(userId)) {
@@ -1246,6 +1247,10 @@ public class UsageStatsService extends SystemService implements
* Called by the Binder stub.
*/
private boolean updatePackageMappingsData() {
// don't update the mappings if a profile user is defined
if (!shouldDeleteObsoleteData(UserHandle.SYSTEM)) {
return true; // return true so job scheduler doesn't reschedule the job
}
// fetch the installed packages outside the lock so it doesn't block package manager.
final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM);
synchronized (mLock) {
@@ -1584,6 +1589,13 @@ public class UsageStatsService extends SystemService implements
mEstimatedLaunchTimeChangedListeners.remove(listener);
}
private boolean shouldDeleteObsoleteData(UserHandle userHandle) {
final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
// If a profile owner is not defined for the given user, obsolete data should be deleted
return dpmInternal == null
|| dpmInternal.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle) == null;
}
private String buildFullToken(String packageName, String token) {
final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1);
sb.append(packageName);
@@ -2862,8 +2874,12 @@ public class UsageStatsService extends SystemService implements
private class MyPackageMonitor extends PackageMonitor {
@Override
public void onPackageRemoved(String packageName, int uid) {
mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 0, packageName)
.sendToTarget();
final int changingUserId = getChangingUserId();
// Only remove the package's data if a profile owner is not defined for the user
if (shouldDeleteObsoleteData(UserHandle.of(changingUserId))) {
mHandler.obtainMessage(MSG_PACKAGE_REMOVED, changingUserId, 0, packageName)
.sendToTarget();
}
super.onPackageRemoved(packageName, uid);
}
}

View File

@@ -117,8 +117,9 @@ class UserUsageStatsService {
mSystemTimeSnapshot = System.currentTimeMillis();
}
void init(final long currentTimeMillis, HashMap<String, Long> installedPackages) {
readPackageMappingsLocked(installedPackages);
void init(final long currentTimeMillis, HashMap<String, Long> installedPackages,
boolean deleteObsoleteData) {
readPackageMappingsLocked(installedPackages, deleteObsoleteData);
mDatabase.init(currentTimeMillis);
if (mDatabase.wasUpgradePerformed()) {
mDatabase.prunePackagesDataOnUpgrade(installedPackages);
@@ -182,12 +183,13 @@ class UserUsageStatsService {
return mDatabase.onPackageRemoved(packageName, timeRemoved);
}
private void readPackageMappingsLocked(HashMap<String, Long> installedPackages) {
private void readPackageMappingsLocked(HashMap<String, Long> installedPackages,
boolean deleteObsoleteData) {
mDatabase.readMappingsLocked();
// Package mappings for the system user are updated after 24 hours via a job scheduled by
// UsageStatsIdleService to ensure restored data is not lost on first boot. Additionally,
// this makes user service initialization a little quicker on subsequent boots.
if (mUserId != UserHandle.USER_SYSTEM) {
if (mUserId != UserHandle.USER_SYSTEM && deleteObsoleteData) {
updatePackageMappingsLocked(installedPackages);
}
}