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);