Restrict visibility of SHORTCUT_INVOCATION events.
UsageStats will not return SHORTCUT_INVOCATION events to callers of #queryEvents and #queryEventsForUser if they don't have visibility, as defined by ShortcutService#hasShortcutHostPermission. Also, add ACCESS_SHORTCUT permission to shell for CTS test and add the ShortcutManagerUsageTest to postsubmit. Bug: 145549490 Test: atest android.app.usage.cts.UsageStatsTest Test: atest android.content.pm.cts.shortcutmanager.ShortcutManagerUsageTest Change-Id: I2a69f061c35c31035a5d0381ab2f42029ec4fffc
This commit is contained in:
@@ -363,6 +363,8 @@ applications that come with the platform
|
||||
<permission name="android.permission.WRITE_DREAM_STATE" />
|
||||
<!-- Permission required to test lights control APIs. -->
|
||||
<permission name="android.permission.CONTROL_DEVICE_LIGHTS" />
|
||||
<!-- Permission required for ShortcutManagerUsageTest CTS test. -->
|
||||
<permission name="android.permission.ACCESS_SHORTCUTS"/>
|
||||
</privapp-permissions>
|
||||
|
||||
<privapp-permissions package="com.android.statementservice">
|
||||
|
||||
@@ -240,6 +240,9 @@
|
||||
<!-- Allows setting brightness from the shell -->
|
||||
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
|
||||
|
||||
<!-- Permission required for CTS test - ShortcutManagerUsageTest -->
|
||||
<uses-permission android:name="android.permission.ACCESS_SHORTCUTS"/>
|
||||
|
||||
<!-- Permissions required to test ambient display. -->
|
||||
<uses-permission android:name="android.permission.READ_DREAM_STATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_DREAM_STATE"/>
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
"include-filter": "android.app.usage.cts.UsageStatsTest"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CtsShortcutManagerTestCases",
|
||||
"options": [
|
||||
{
|
||||
"include-filter": "android.content.pm.cts.shortcutmanager.ShortcutManagerUsageTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ShortcutServiceInternal;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Binder;
|
||||
@@ -156,6 +157,8 @@ public class UsageStatsService extends SystemService implements
|
||||
PackageManagerInternal mPackageManagerInternal;
|
||||
// Do not use directly. Call getDpmInternal() instead
|
||||
DevicePolicyManagerInternal mDpmInternal;
|
||||
// Do not use directly. Call getShortcutServiceInternal() instead
|
||||
ShortcutServiceInternal mShortcutServiceInternal;
|
||||
|
||||
private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
|
||||
private final SparseBooleanArray mUserUnlockedStates = new SparseBooleanArray();
|
||||
@@ -267,6 +270,8 @@ public class UsageStatsService extends SystemService implements
|
||||
if (phase == PHASE_SYSTEM_SERVICES_READY) {
|
||||
// initialize mDpmInternal
|
||||
getDpmInternal();
|
||||
// initialize mShortcutServiceInternal
|
||||
getShortcutServiceInternal();
|
||||
|
||||
if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
|
||||
try {
|
||||
@@ -400,6 +405,13 @@ public class UsageStatsService extends SystemService implements
|
||||
return mDpmInternal;
|
||||
}
|
||||
|
||||
private ShortcutServiceInternal getShortcutServiceInternal() {
|
||||
if (mShortcutServiceInternal == null) {
|
||||
mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
|
||||
}
|
||||
return mShortcutServiceInternal;
|
||||
}
|
||||
|
||||
private void readUsageSourceSetting() {
|
||||
synchronized (mLock) {
|
||||
mUsageSource = Settings.Global.getInt(getContext().getContentResolver(),
|
||||
@@ -469,6 +481,16 @@ public class UsageStatsService extends SystemService implements
|
||||
return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
|
||||
}
|
||||
|
||||
private boolean shouldHideShortcutInvocationEvents(int userId, String callingPackage,
|
||||
int callingPid, int callingUid) {
|
||||
final ShortcutServiceInternal shortcutServiceInternal = getShortcutServiceInternal();
|
||||
if (shortcutServiceInternal != null) {
|
||||
return !shortcutServiceInternal.hasShortcutHostPermission(userId, callingPackage,
|
||||
callingPid, callingUid);
|
||||
}
|
||||
return true; // hide by default if we can't verify visibility
|
||||
}
|
||||
|
||||
private static void deleteRecursively(File f) {
|
||||
File[] files = f.listFiles();
|
||||
if (files != null) {
|
||||
@@ -1008,7 +1030,7 @@ public class UsageStatsService extends SystemService implements
|
||||
* Called by the Binder stub.
|
||||
*/
|
||||
UsageEvents queryEvents(int userId, long beginTime, long endTime,
|
||||
boolean shouldObfuscateInstantApps) {
|
||||
boolean shouldObfuscateInstantApps, boolean shouldHideShortcutInvocationEvents) {
|
||||
synchronized (mLock) {
|
||||
if (!mUserUnlockedStates.get(userId)) {
|
||||
Slog.w(TAG, "Failed to query events for locked user " + userId);
|
||||
@@ -1019,7 +1041,8 @@ public class UsageStatsService extends SystemService implements
|
||||
if (service == null) {
|
||||
return null; // user was stopped or removed
|
||||
}
|
||||
return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
|
||||
return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps,
|
||||
shouldHideShortcutInvocationEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1418,14 +1441,18 @@ public class UsageStatsService extends SystemService implements
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
|
||||
Binder.getCallingUid(), UserHandle.getCallingUserId());
|
||||
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
|
||||
callingUid, userId);
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
|
||||
userId, callingPackage, callingPid, callingUid);
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
|
||||
obfuscateInstantApps);
|
||||
obfuscateInstantApps, hideShortcutInvocationEvents);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -1456,19 +1483,24 @@ public class UsageStatsService extends SystemService implements
|
||||
return null;
|
||||
}
|
||||
|
||||
if (userId != UserHandle.getCallingUserId()) {
|
||||
final int callingUserId = UserHandle.getCallingUserId();
|
||||
if (userId != callingUserId) {
|
||||
getContext().enforceCallingPermission(
|
||||
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
|
||||
"No permission to query usage stats for this user");
|
||||
}
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
|
||||
Binder.getCallingUid(), UserHandle.getCallingUserId());
|
||||
callingUid, callingUserId);
|
||||
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
|
||||
userId, callingPackage, callingPid, callingUid);
|
||||
return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
|
||||
obfuscateInstantApps);
|
||||
obfuscateInstantApps, hideShortcutInvocationEvents);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -2087,7 +2119,7 @@ public class UsageStatsService extends SystemService implements
|
||||
public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime,
|
||||
boolean shouldObfuscateInstantApps) {
|
||||
return UsageStatsService.this.queryEvents(
|
||||
userId, beginTime, endTime, shouldObfuscateInstantApps);
|
||||
userId, beginTime, endTime, shouldObfuscateInstantApps, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -482,7 +482,7 @@ class UserUsageStatsService {
|
||||
}
|
||||
|
||||
UsageEvents queryEvents(final long beginTime, final long endTime,
|
||||
boolean obfuscateInstantApps) {
|
||||
boolean obfuscateInstantApps, boolean hideShortcutInvocationEvents) {
|
||||
if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
|
||||
return null;
|
||||
}
|
||||
@@ -500,6 +500,10 @@ class UserUsageStatsService {
|
||||
}
|
||||
|
||||
Event event = stats.events.get(i);
|
||||
if (hideShortcutInvocationEvents
|
||||
&& event.mEventType == Event.SHORTCUT_INVOCATION) {
|
||||
continue;
|
||||
}
|
||||
if (obfuscateInstantApps) {
|
||||
event = event.getObfuscatedIfInstantApp();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user