Update certain APIs to require the REPORT_USAGE_STATS permission.

Add requirement of either being the system or having the
REPORT_USAGE_STATS permission in order to call any report events related
APIs. This includes the reportChooserSelection and reportUserInteraction
APIs.

Also add the permission to Shell so the APIs can be tested via CTS.

Bug: 296056771
Bug: 218679369
Test: atest CtsUsageStatsTest
Change-Id: I3b28e00b9da73cd4bc051f3c5e03e29a734a1df0
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 323f65f..0364ede 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);