Merge "Update certain APIs to require the REPORT_USAGE_STATS permission." into main
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index ecf16439..2a10ed1 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1106,6 +1106,7 @@
* <p><em>This method is only for use by the system</em>
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.REPORT_USAGE_STATS)
public void reportUserInteraction(@NonNull String packageName, int userId) {
try {
mService.reportUserInteraction(packageName, userId);
@@ -1396,6 +1397,7 @@
* {@link UsageEvents}
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.REPORT_USAGE_STATS)
public void reportChooserSelection(String packageName, int userId, String contentType,
String[] annotations, String action) {
try {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bd3b83e..ffe28a6 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -167,6 +167,7 @@
<uses-permission android:name="android.permission.FORCE_BACK" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+ <uses-permission android:name="android.permission.REPORT_USAGE_STATS" />
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" />
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index e738d29..90b798c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -2061,6 +2061,15 @@
return mode == AppOpsManager.MODE_ALLOWED;
}
+ private boolean canReportUsageStats() {
+ if (isCallingUidSystem()) {
+ return true; // System UID can always report UsageStats
+ }
+
+ return getContext().checkCallingPermission(Manifest.permission.REPORT_USAGE_STATS)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
private boolean hasObserverPermission() {
final int callingUid = Binder.getCallingUid();
DevicePolicyManagerInternal dpmInternal = getDpmInternal();
@@ -2541,14 +2550,19 @@
@Override
public void reportChooserSelection(@NonNull String packageName, int userId,
@NonNull String contentType, String[] annotations, @NonNull String action) {
- if (packageName == null) {
- throw new IllegalArgumentException("Package selection must not be null.");
- }
- // A valid contentType and action must be provided for chooser selection events.
- if (contentType == null || contentType.isBlank()
- || action == null || action.isBlank()) {
+ // A valid package name, content type, and action must be provided for these events
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(contentType);
+ Objects.requireNonNull(action);
+ if (contentType.isBlank() || action.isBlank()) {
return;
}
+
+ if (!canReportUsageStats()) {
+ throw new SecurityException("Only the system or holders of the REPORT_USAGE_STATS"
+ + " permission are allowed to call reportChooserSelection");
+ }
+
// Verify if this package exists before reporting an event for it.
if (mPackageManagerInternal.getPackageUid(packageName, 0, userId) < 0) {
Slog.w(TAG, "Event report user selecting an invalid package");
@@ -2566,9 +2580,11 @@
@Override
public void reportUserInteraction(String packageName, int userId) {
Objects.requireNonNull(packageName);
- if (!isCallingUidSystem()) {
- throw new SecurityException("Only system is allowed to call reportUserInteraction");
+ if (!canReportUsageStats()) {
+ throw new SecurityException("Only the system or holders of the REPORT_USAGE_STATS"
+ + " permission are allowed to call reportUserInteraction");
}
+
final Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime());
event.mPackage = packageName;
reportEventOrAddToQueue(userId, event);