From ad623015a119efe9b63f594af9c4703f40a0c27b Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Mon, 15 May 2017 09:29:34 -0700 Subject: Restrict access to instant app data in usage stats - Events are obfuscated based on whether the app was instant or not at the time each event was logged. - UsageStats are obfuscated based on whether each app is instant or not at the moment. Bug 38202133 Test: Manual test using UsageStatsTest and instant apps Change-Id: I3c74309196b88d010d317cb0dd6749bf4624e876 --- .../android/server/usage/UsageStatsService.java | 63 ++++++++++++++++++---- .../com/android/server/usage/UsageStatsXmlV1.java | 11 +++- .../server/usage/UserUsageStatsService.java | 12 +++-- 3 files changed, 69 insertions(+), 17 deletions(-) (limited to 'services/usage/java') diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 4ba457d211a3..0de3c7c75016 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -39,6 +39,7 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; @@ -80,6 +81,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.LocalServices; import com.android.server.SystemService; import java.io.File; @@ -137,6 +139,7 @@ public class UsageStatsService extends SystemService implements AppOpsManager mAppOps; UserManager mUserManager; PackageManager mPackageManager; + PackageManagerInternal mPackageManagerInternal; AppWidgetManager mAppWidgetManager; IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; @@ -179,6 +182,7 @@ public class UsageStatsService extends SystemService implements mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); mPackageManager = getContext().getPackageManager(); + mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mHandler = new H(BackgroundThread.get().getLooper()); File systemDataDir = new File(Environment.getDataDirectory(), "system"); @@ -407,6 +411,10 @@ public class UsageStatsService extends SystemService implements } } + private boolean shouldObfuscateInstantAppsForCaller(int callingUid) { + return !mPackageManagerInternal.canAccessInstantApps(callingUid); + } + void clearAppIdleForPackage(String packageName, int userId) { synchronized (mAppIdleLock) { mAppIdleHistory.clearUsage(packageName, userId); @@ -704,6 +712,11 @@ public class UsageStatsService extends SystemService implements final long elapsedRealtime = SystemClock.elapsedRealtime(); convertToSystemTimeLocked(event); + if (event.getPackageName() != null + && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) { + event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP; + } + final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); service.reportEvent(event); @@ -807,7 +820,8 @@ public class UsageStatsService extends SystemService implements /** * Called by the Binder stub. */ - List queryUsageStats(int userId, int bucketType, long beginTime, long endTime) { + List queryUsageStats(int userId, int bucketType, long beginTime, long endTime, + boolean obfuscateInstantApps) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); if (!validRange(timeNow, beginTime, endTime)) { @@ -816,7 +830,20 @@ public class UsageStatsService extends SystemService implements final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); - return service.queryUsageStats(bucketType, beginTime, endTime); + List list = service.queryUsageStats(bucketType, beginTime, endTime); + + // Mangle instant app names *using their current state (not whether they were ephemeral + // when the data was recorded)*. + if (obfuscateInstantApps) { + for (int i = list.size() - 1; i >= 0; i--) { + final UsageStats stats = list.get(i); + if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) { + list.set(i, stats.getObfuscatedForInstantApp()); + } + } + } + + return list; } } @@ -840,7 +867,8 @@ public class UsageStatsService extends SystemService implements /** * Called by the Binder stub. */ - UsageEvents queryEvents(int userId, long beginTime, long endTime) { + UsageEvents queryEvents(int userId, long beginTime, long endTime, + boolean shouldObfuscateInstantApps) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); if (!validRange(timeNow, beginTime, endTime)) { @@ -849,7 +877,7 @@ public class UsageStatsService extends SystemService implements final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); - return service.queryEvents(beginTime, endTime); + return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps); } } @@ -884,10 +912,15 @@ public class UsageStatsService extends SystemService implements } } - boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) { + boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime, + boolean shouldObfuscateInstantApps) { if (isParoledOrCharging()) { return false; } + if (shouldObfuscateInstantApps && + mPackageManagerInternal.isPackageEphemeral(userId, packageName)) { + return false; + } return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime); } @@ -1353,11 +1386,14 @@ public class UsageStatsService extends SystemService implements return null; } + final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( + Binder.getCallingUid()); + final int userId = UserHandle.getCallingUserId(); final long token = Binder.clearCallingIdentity(); try { final List results = UsageStatsService.this.queryUsageStats( - userId, bucketType, beginTime, endTime); + userId, bucketType, beginTime, endTime, obfuscateInstantApps); if (results != null) { return new ParceledListSlice<>(results); } @@ -1395,10 +1431,14 @@ public class UsageStatsService extends SystemService implements return null; } + final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( + Binder.getCallingUid()); + final int userId = UserHandle.getCallingUserId(); final long token = Binder.clearCallingIdentity(); try { - return UsageStatsService.this.queryEvents(userId, beginTime, endTime); + return UsageStatsService.this.queryEvents(userId, beginTime, endTime, + obfuscateInstantApps); } finally { Binder.restoreCallingIdentity(token); } @@ -1412,10 +1452,12 @@ public class UsageStatsService extends SystemService implements } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } + final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( + Binder.getCallingUid()); final long token = Binder.clearCallingIdentity(); try { return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, - SystemClock.elapsedRealtime()); + SystemClock.elapsedRealtime(), obfuscateInstantApps); } finally { Binder.restoreCallingIdentity(token); } @@ -1647,9 +1689,10 @@ public class UsageStatsService extends SystemService implements @Override public List queryUsageStatsForUser( - int userId, int intervalType, long beginTime, long endTime) { + int userId, int intervalType, long beginTime, long endTime, + boolean obfuscateInstantApps) { return UsageStatsService.this.queryUsageStats( - userId, intervalType, beginTime, endTime); + userId, intervalType, beginTime, endTime, obfuscateInstantApps); } } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java index 96f3305e2538..cc53a9cc0b70 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java +++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java @@ -26,7 +26,10 @@ import android.app.usage.TimeSparseArray; import android.app.usage.UsageEvents; import android.app.usage.UsageStats; import android.content.res.Configuration; +import android.text.TextUtils; import android.util.ArrayMap; +import android.util.Log; +import android.util.LogWriter; import java.io.IOException; import java.net.ProtocolException; @@ -35,6 +38,8 @@ import java.net.ProtocolException; * UsageStats reader/writer for version 1 of the XML format. */ final class UsageStatsXmlV1 { + private static final String TAG = "UsageStatsXmlV1"; + private static final String PACKAGES_TAG = "packages"; private static final String PACKAGE_TAG = "package"; @@ -51,6 +56,7 @@ final class UsageStatsXmlV1 { // Attributes private static final String PACKAGE_ATTR = "package"; + private static final String FLAGS_ATTR = "flags"; private static final String CLASS_ATTR = "class"; private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive"; private static final String COUNT_ATTR = "count"; @@ -70,7 +76,6 @@ final class UsageStatsXmlV1 { if (pkg == null) { throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); } - final UsageStats stats = statsOut.getOrCreateUsageStats(pkg); // Apply the offset to the beginTime to find the absolute time. @@ -149,11 +154,12 @@ final class UsageStatsXmlV1 { if (packageName == null) { throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present"); } - final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR); final UsageEvents.Event event = statsOut.buildEvent(packageName, className); + event.mFlags = XmlUtils.readIntAttribute(parser, FLAGS_ATTR, 0); + // Apply the offset to the beginTime to find the absolute time of this event. event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR); @@ -256,6 +262,7 @@ final class UsageStatsXmlV1 { if (event.mClass != null) { XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass); } + XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags); XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType); switch (event.mEventType) { diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 8d335a51bb55..0abbb82a68a1 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -19,11 +19,8 @@ package com.android.server.usage; import android.app.usage.ConfigurationStats; import android.app.usage.TimeSparseArray; import android.app.usage.UsageEvents; -import android.app.usage.UsageEvents.Event; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.SystemClock; import android.content.Context; @@ -312,7 +309,8 @@ class UserUsageStatsService { return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner); } - UsageEvents queryEvents(final long beginTime, final long endTime) { + UsageEvents queryEvents(final long beginTime, final long endTime, + boolean obfuscateInstantApps) { final ArraySet names = new ArraySet<>(); List results = queryStats(UsageStatsManager.INTERVAL_DAILY, beginTime, endTime, new StatCombiner() { @@ -334,7 +332,10 @@ class UserUsageStatsService { return; } - final UsageEvents.Event event = stats.events.valueAt(i); + UsageEvents.Event event = stats.events.valueAt(i); + if (obfuscateInstantApps) { + event = event.getObfuscatedIfInstantApp(); + } names.add(event.mPackage); if (event.mClass != null) { names.add(event.mClass); @@ -586,6 +587,7 @@ class UserUsageStatsService { if (event.mShortcutId != null) { pw.printPair("shortcutId", event.mShortcutId); } + pw.printHexPair("flags", event.mFlags); pw.println(); } pw.decreaseIndent(); -- cgit v1.2.3-59-g8ed1b