Merge "Obfuscate visibility of notification-related events."
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e21e319cd
@@ -41,6 +41,43 @@ public final class UsageEvents implements Parcelable {
|
||||
/** @hide */
|
||||
public static final String INSTANT_APP_CLASS_NAME = "android.instant_class";
|
||||
|
||||
/** @hide */
|
||||
public static final String OBFUSCATED_NOTIFICATION_CHANNEL_ID = "unknown_channel_id";
|
||||
|
||||
/**
|
||||
* Flag: indicates to not obfuscate or hide any usage event data when being queried.
|
||||
* @hide
|
||||
*/
|
||||
public static final int SHOW_ALL_EVENT_DATA = 0x00000000;
|
||||
|
||||
/**
|
||||
* Flag: indicates to obfuscate package and class names for instant apps when querying usage
|
||||
* events.
|
||||
* @hide
|
||||
*/
|
||||
public static final int OBFUSCATE_INSTANT_APPS = 0x00000001;
|
||||
|
||||
/**
|
||||
* Flag: indicates to hide all {@link Event#SHORTCUT_INVOCATION} events when querying usage
|
||||
* events.
|
||||
* @hide
|
||||
*/
|
||||
public static final int HIDE_SHORTCUT_EVENTS = 0x00000002;
|
||||
|
||||
/**
|
||||
* Flag: indicates to obfuscate the notification channel id for all notification events,
|
||||
* such as {@link Event#NOTIFICATION_SEEN} and {@link Event#NOTIFICATION_INTERRUPTION} events,
|
||||
* when querying usage events.
|
||||
* @hide
|
||||
*/
|
||||
public static final int OBFUSCATE_NOTIFICATION_EVENTS = 0x00000004;
|
||||
|
||||
/**
|
||||
* Flag: indicates to hide all {@link Event#LOCUS_ID_SET} events when querying usage events.
|
||||
* @hide
|
||||
*/
|
||||
public static final int HIDE_LOCUS_EVENTS = 0x00000008;
|
||||
|
||||
/**
|
||||
* An event representing a state change for a component.
|
||||
*/
|
||||
@@ -627,6 +664,13 @@ public final class UsageEvents implements Parcelable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public Event getObfuscatedNotificationEvent() {
|
||||
final Event ret = new Event(this);
|
||||
ret.mNotificationChannelId = OBFUSCATED_NOTIFICATION_CHANNEL_ID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locusId for this event if the event is of type {@link #LOCUS_ID_SET},
|
||||
* otherwise it returns null.
|
||||
|
||||
@@ -381,6 +381,8 @@ applications that come with the platform
|
||||
<permission name="android.permission.REBOOT"/>
|
||||
<!-- Permission required for access VIBRATOR_STATE. -->
|
||||
<permission name="android.permission.ACCESS_VIBRATOR_STATE"/>
|
||||
<!-- Permission required for UsageStatsTest CTS test. -->
|
||||
<permission name="android.permission.MANAGE_NOTIFICATIONS"/>
|
||||
</privapp-permissions>
|
||||
|
||||
<privapp-permissions package="com.android.statementservice">
|
||||
|
||||
@@ -253,7 +253,8 @@
|
||||
<!-- Permission required for CTS test - ShortcutManagerUsageTest -->
|
||||
<uses-permission android:name="android.permission.ACCESS_SHORTCUTS"/>
|
||||
|
||||
<!-- Permission required for CTS test - UsageStatsTest -->
|
||||
<!-- Permissions required for CTS test - UsageStatsTest -->
|
||||
<uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"/>
|
||||
|
||||
<!-- Permissions required to test ambient display. -->
|
||||
|
||||
@@ -216,17 +216,11 @@ public abstract class UsageStatsManagerInternal {
|
||||
/**
|
||||
* Returns the events for the user in the given time period.
|
||||
*
|
||||
* @param obfuscateInstantApps whether instant app package names need to be obfuscated in the
|
||||
* result.
|
||||
* @param hideShortcutInvocationEvents whether the {@link UsageEvents.Event#SHORTCUT_INVOCATION}
|
||||
* events need to be excluded from the result.
|
||||
* @param hideLocusIdEvents whether the {@link UsageEvents.Event#LOCUS_ID_SET}
|
||||
* events need to be excluded from the result.
|
||||
*
|
||||
* @param flags defines the visibility of certain usage events - see flags defined in
|
||||
* {@link UsageEvents}.
|
||||
*/
|
||||
public abstract UsageEvents queryEventsForUser(@UserIdInt int userId, long beginTime,
|
||||
long endTime, boolean obfuscateInstantApps, boolean hideShortcutInvocationEvents,
|
||||
boolean hideLocusIdEvents);
|
||||
long endTime, int flags);
|
||||
|
||||
/**
|
||||
* Used to persist the last time a job was run for this app, in order to make decisions later
|
||||
|
||||
@@ -59,7 +59,7 @@ class UsageStatsQueryHelper {
|
||||
*/
|
||||
boolean querySince(long sinceTime) {
|
||||
UsageEvents usageEvents = mUsageStatsManagerInternal.queryEventsForUser(
|
||||
mUserId, sinceTime, System.currentTimeMillis(), false, false, false);
|
||||
mUserId, sinceTime, System.currentTimeMillis(), UsageEvents.SHOW_ALL_EVENT_DATA);
|
||||
if (usageEvents == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.android.server.people.data;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -189,7 +189,7 @@ public final class UsageStatsQueryHelperTest {
|
||||
private void addUsageEvents(UsageEvents.Event... events) {
|
||||
UsageEvents usageEvents = new UsageEvents(Arrays.asList(events), new String[]{});
|
||||
when(mUsageStatsManagerInternal.queryEventsForUser(anyInt(), anyLong(), anyLong(),
|
||||
anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(usageEvents);
|
||||
eq(UsageEvents.SHOW_ALL_EVENT_DATA))).thenReturn(usageEvents);
|
||||
}
|
||||
|
||||
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
|
||||
|
||||
@@ -500,6 +500,19 @@ public class UsageStatsService extends SystemService implements
|
||||
== PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obfuscate both {@link UsageEvents.Event#NOTIFICATION_SEEN} and
|
||||
* {@link UsageEvents.Event#NOTIFICATION_INTERRUPTION} events if the provided calling uid does
|
||||
* not hold the {@link android.Manifest.permission.MANAGE_NOTIFICATIONS} permission.
|
||||
*/
|
||||
private boolean shouldObfuscateNotificationEvents(int callingPid, int callingUid) {
|
||||
if (callingUid == Process.SYSTEM_UID) {
|
||||
return false;
|
||||
}
|
||||
return !(getContext().checkPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS,
|
||||
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
private static void deleteRecursively(File f) {
|
||||
File[] files = f.listFiles();
|
||||
if (files != null) {
|
||||
@@ -1038,9 +1051,7 @@ public class UsageStatsService extends SystemService implements
|
||||
/**
|
||||
* Called by the Binder stub.
|
||||
*/
|
||||
UsageEvents queryEvents(int userId, long beginTime, long endTime,
|
||||
boolean shouldObfuscateInstantApps, boolean shouldHideShortcutInvocationEvents,
|
||||
boolean shouldHideLocusIdEvents) {
|
||||
UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) {
|
||||
synchronized (mLock) {
|
||||
if (!mUserUnlockedStates.get(userId)) {
|
||||
Slog.w(TAG, "Failed to query events for locked user " + userId);
|
||||
@@ -1051,8 +1062,7 @@ public class UsageStatsService extends SystemService implements
|
||||
if (service == null) {
|
||||
return null; // user was stopped or removed
|
||||
}
|
||||
return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps,
|
||||
shouldHideShortcutInvocationEvents, shouldHideLocusIdEvents);
|
||||
return service.queryEvents(beginTime, endTime, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1475,10 +1485,15 @@ public class UsageStatsService extends SystemService implements
|
||||
try {
|
||||
final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
|
||||
userId, callingPackage, callingPid, callingUid);
|
||||
boolean shouldHideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
|
||||
obfuscateInstantApps, hideShortcutInvocationEvents,
|
||||
shouldHideLocusIdEvents);
|
||||
final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
|
||||
final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
|
||||
callingPid, callingUid);
|
||||
int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
|
||||
if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
|
||||
if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
|
||||
if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
|
||||
if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -1525,10 +1540,15 @@ public class UsageStatsService extends SystemService implements
|
||||
try {
|
||||
final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
|
||||
userId, callingPackage, callingPid, callingUid);
|
||||
boolean shouldHideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
|
||||
obfuscateInstantApps, hideShortcutInvocationEvents,
|
||||
shouldHideLocusIdEvents);
|
||||
final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
|
||||
callingPid, callingUid);
|
||||
boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
|
||||
int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
|
||||
if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
|
||||
if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
|
||||
if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
|
||||
if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -2144,12 +2164,8 @@ public class UsageStatsService extends SystemService implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime,
|
||||
boolean obfuscateInstantApps, boolean shouldHideShortcutInvocationEvents,
|
||||
boolean shouldHideLocusIdEvents) {
|
||||
return UsageStatsService.this.queryEvents(
|
||||
userId, beginTime, endTime, obfuscateInstantApps,
|
||||
shouldHideShortcutInvocationEvents, shouldHideLocusIdEvents);
|
||||
public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime, int flags) {
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,10 @@ package com.android.server.usage;
|
||||
|
||||
import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
|
||||
import static android.app.usage.UsageEvents.Event.DEVICE_STARTUP;
|
||||
import static android.app.usage.UsageEvents.HIDE_LOCUS_EVENTS;
|
||||
import static android.app.usage.UsageEvents.HIDE_SHORTCUT_EVENTS;
|
||||
import static android.app.usage.UsageEvents.OBFUSCATE_INSTANT_APPS;
|
||||
import static android.app.usage.UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
|
||||
import static android.app.usage.UsageStatsManager.INTERVAL_BEST;
|
||||
import static android.app.usage.UsageStatsManager.INTERVAL_COUNT;
|
||||
import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
|
||||
@@ -481,8 +485,7 @@ class UserUsageStatsService {
|
||||
return queryStats(bucketType, beginTime, endTime, sEventStatsCombiner);
|
||||
}
|
||||
|
||||
UsageEvents queryEvents(final long beginTime, final long endTime, boolean obfuscateInstantApps,
|
||||
boolean hideShortcutInvocationEvents, boolean hideLocusIdEvents) {
|
||||
UsageEvents queryEvents(final long beginTime, final long endTime, int flags) {
|
||||
if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
|
||||
return null;
|
||||
}
|
||||
@@ -500,15 +503,22 @@ class UserUsageStatsService {
|
||||
}
|
||||
|
||||
Event event = stats.events.get(i);
|
||||
if (hideShortcutInvocationEvents
|
||||
&& event.mEventType == Event.SHORTCUT_INVOCATION) {
|
||||
final int eventType = event.mEventType;
|
||||
if (eventType == Event.SHORTCUT_INVOCATION
|
||||
&& (flags & HIDE_SHORTCUT_EVENTS) == HIDE_SHORTCUT_EVENTS) {
|
||||
continue;
|
||||
}
|
||||
if (hideLocusIdEvents
|
||||
&& event.mEventType == Event.LOCUS_ID_SET) {
|
||||
if (eventType == Event.LOCUS_ID_SET
|
||||
&& (flags & HIDE_LOCUS_EVENTS) == HIDE_LOCUS_EVENTS) {
|
||||
continue;
|
||||
}
|
||||
if (obfuscateInstantApps) {
|
||||
if ((eventType == Event.NOTIFICATION_SEEN
|
||||
|| eventType == Event.NOTIFICATION_INTERRUPTION)
|
||||
&& (flags & OBFUSCATE_NOTIFICATION_EVENTS)
|
||||
== OBFUSCATE_NOTIFICATION_EVENTS) {
|
||||
event = event.getObfuscatedNotificationEvent();
|
||||
}
|
||||
if ((flags & OBFUSCATE_INSTANT_APPS) == OBFUSCATE_INSTANT_APPS) {
|
||||
event = event.getObfuscatedIfInstantApp();
|
||||
}
|
||||
if (event.mPackage != null) {
|
||||
|
||||
Reference in New Issue
Block a user