UsageStats: Support event query with specific user id.

Add support the usage event query for specific user.

Bug: 194321117
Test: atest CtsUsageStatsTestCases:android.app.usage.cts.UsageStatsTest
Change-Id: Iaa9d138bef5bce4051b746985860f3e9757ee6b3
diff --git a/core/java/android/app/usage/UsageEventsQuery.java b/core/java/android/app/usage/UsageEventsQuery.java
index 8c63d18..3cd2923 100644
--- a/core/java/android/app/usage/UsageEventsQuery.java
+++ b/core/java/android/app/usage/UsageEventsQuery.java
@@ -19,9 +19,11 @@
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.app.usage.UsageEvents.Event;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.ArraySet;
 
 import com.android.internal.util.ArrayUtils;
@@ -40,11 +42,13 @@
     private final @CurrentTimeMillisLong long mBeginTimeMillis;
     private final @CurrentTimeMillisLong long mEndTimeMillis;
     private final @Event.EventType int[] mEventTypes;
+    private final @UserIdInt int mUserId;
 
     private UsageEventsQuery(@NonNull Builder builder) {
         mBeginTimeMillis = builder.mBeginTimeMillis;
         mEndTimeMillis = builder.mEndTimeMillis;
         mEventTypes = ArrayUtils.convertToIntArray(builder.mEventTypes);
+        mUserId = builder.mUserId;
     }
 
     private UsageEventsQuery(Parcel in) {
@@ -53,6 +57,7 @@
         int eventTypesLength = in.readInt();
         mEventTypes = new int[eventTypesLength];
         in.readIntArray(mEventTypes);
+        mUserId = in.readInt();
     }
 
     /**
@@ -87,6 +92,11 @@
         return eventTypeSet;
     }
 
+    /** @hide */
+    public @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -98,6 +108,7 @@
         dest.writeLong(mEndTimeMillis);
         dest.writeInt(mEventTypes.length);
         dest.writeIntArray(mEventTypes);
+        dest.writeInt(mUserId);
     }
 
     @NonNull
@@ -126,6 +137,7 @@
         private final @CurrentTimeMillisLong long mBeginTimeMillis;
         private final @CurrentTimeMillisLong long mEndTimeMillis;
         private final ArraySet<Integer> mEventTypes = new ArraySet<>();
+        private @UserIdInt int mUserId = UserHandle.USER_NULL;
 
         /**
          * Constructor that specifies the period for which to return events.
@@ -169,5 +181,15 @@
             }
             return this;
         }
+
+        /**
+         * Specifices the user id for the query.
+         * @param userId for whom the query should be performed.
+         * @hide
+         */
+        public @NonNull Builder setUserId(@UserIdInt int userId) {
+            mUserId = userId;
+            return this;
+        }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 72db7fe..ccd4ce0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -2395,7 +2395,19 @@
                 return null;
             }
 
-            return queryEventsHelper(UserHandle.getCallingUserId(), query.getBeginTimeMillis(),
+            final int callingUserId = UserHandle.getCallingUserId();
+            int userId = query.getUserId();
+            if (userId == UserHandle.USER_NULL) {
+                // Convert userId to actual user Id if not specified in the query object.
+                userId = callingUserId;
+            }
+            if (userId != callingUserId) {
+                getContext().enforceCallingPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                        "No permission to query usage stats for user " + userId);
+            }
+
+            return queryEventsHelper(userId, query.getBeginTimeMillis(),
                     query.getEndTimeMillis(), callingPackage, query.getEventTypeFilter());
         }