Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c681f53 authored by Xin Guan's avatar Xin Guan Committed by Android (Google) Code Review
Browse files

Merge "UsageStats: Addressing API review comments." into main

parents 147339d5 ae94902f
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -9379,15 +9379,15 @@ package android.app.usage {
    method public int describeContents();
    method public long getBeginTimeMillis();
    method public long getEndTimeMillis();
    method @NonNull public java.util.Set<java.lang.Integer> getEventTypes();
    method @NonNull public int[] getEventTypes();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.UsageEventsQuery> CREATOR;
  }
  public static final class UsageEventsQuery.Builder {
    ctor public UsageEventsQuery.Builder(long, long);
    method @NonNull public android.app.usage.UsageEventsQuery.Builder addEventTypes(@NonNull int...);
    method @NonNull public android.app.usage.UsageEventsQuery build();
    method @NonNull public android.app.usage.UsageEventsQuery.Builder setEventTypes(@NonNull int...);
  }
  public final class UsageStats implements android.os.Parcelable {
@@ -9414,7 +9414,7 @@ package android.app.usage {
    method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
    method public java.util.List<android.app.usage.EventStats> queryEventStats(int, long, long);
    method public android.app.usage.UsageEvents queryEvents(long, long);
    method @FlaggedApi("android.app.usage.filter_based_event_query_api") @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public android.app.usage.UsageEvents queryEvents(@NonNull android.app.usage.UsageEventsQuery);
    method @FlaggedApi("android.app.usage.filter_based_event_query_api") @Nullable @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public android.app.usage.UsageEvents queryEvents(@NonNull android.app.usage.UsageEventsQuery);
    method public android.app.usage.UsageEvents queryEventsForSelf(long, long);
    method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
    field @FlaggedApi("android.app.usage.user_interaction_type_api") public static final String EXTRA_EVENT_ACTION = "android.app.usage.extra.EVENT_ACTION";
+27 −24
Original line number Diff line number Diff line
@@ -29,9 +29,6 @@ import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * An Object-Oriented representation for a {@link UsageEvents} query.
@@ -77,19 +74,17 @@ public final class UsageEventsQuery implements Parcelable {
    }

    /**
     * Returns the set of usage event types for the query.
     * <em>Note: An empty set indicates query for all usage events. </em>
     * Retrieves the usage event types for the query.
     * <p>Note that an empty array indicates querying all usage event types, and it may
     * cause additional system overhead when calling
     * {@link UsageStatsManager#queryEvents(UsageEventsQuery)}. Apps are encouraged to
     * provide a list of event types via {@link Builder#setEventTypes(int...)}</p>
     *
     * @return an array contains the usage event types that was previously set using
     *         {@link Builder#setEventTypes(int...)} or an empty array if no value has been set.
     */
    public @NonNull Set<Integer> getEventTypes() {
        if (ArrayUtils.isEmpty(mEventTypes)) {
            return Collections.emptySet();
        }

        HashSet<Integer> eventTypeSet = new HashSet<>();
        for (int eventType : mEventTypes) {
            eventTypeSet.add(eventType);
        }
        return eventTypeSet;
    public @NonNull @Event.EventType int[] getEventTypes() {
        return Arrays.copyOf(mEventTypes, mEventTypes.length);
    }

    /** @hide */
@@ -125,11 +120,6 @@ public final class UsageEventsQuery implements Parcelable {
                }
            };

    /** @hide */
    public int[] getEventTypeFilter() {
        return Arrays.copyOf(mEventTypes, mEventTypes.length);
    }

    /**
     * Builder for UsageEventsQuery.
     */
@@ -166,12 +156,25 @@ public final class UsageEventsQuery implements Parcelable {
        }

        /**
         * Specifies the list of usage event types to be included in the query.
         * @param eventTypes List of the usage event types. See {@link UsageEvents.Event}
         * Sets the list of usage event types to be included in the query.
         *
         * @throws llegalArgumentException if the event type is not valid.
         * <p>Note: </p> An empty array will be returned by
         * {@link UsageEventsQuery#getEventTypes()} without calling this method, which indicates
         * querying for all event types. Apps are encouraged to provide a list of event types.
         * Only the matching types supplied will be used to query.
         *
         * @param eventTypes the array of the usage event types. See {@link UsageEvents.Event}.
         * @throws NullPointerException if {@code eventTypes} is {@code null} or empty.
         * @throws IllegalArgumentException if any of event types are invalid.
         * @see UsageEventsQuery#getEventTypes()
         * @see UsageStatsManager#queryEvents(UsageEventsQuery)
         */
        public @NonNull Builder addEventTypes(@NonNull @Event.EventType int... eventTypes) {
        public @NonNull Builder setEventTypes(@NonNull @Event.EventType int... eventTypes) {
            if (eventTypes == null || eventTypes.length == 0) {
                throw new NullPointerException("eventTypes is null or empty");
            }

            mEventTypes.clear();
            for (int i = 0; i < eventTypes.length; i++) {
                final int eventType = eventTypes[i];
                if (eventType < Event.NONE || eventType > Event.MAX_EVENT_TYPE) {
+3 −2
Original line number Diff line number Diff line
@@ -602,14 +602,15 @@ public final class UsageStatsManager {

    /**
     * Query for events with specific UsageEventsQuery object.
     *
     * <em>Note: if the user's device is not in an unlocked state (as defined by
     * {@link UserManager#isUserUnlocked()}), then {@code null} will be returned.</em>
     *
     * @param query The query object used to specify the query parameters.
     * @return A {@link UsageEvents}.
     * @return A {@link UsageEvents} which contains the events matching the query parameters.
     */
    @FlaggedApi(Flags.FLAG_FILTER_BASED_EVENT_QUERY_API)
    @NonNull
    @Nullable
    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
    public UsageEvents queryEvents(@NonNull UsageEventsQuery query) {
        try {
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ android_test {
        "frameworks-core-util-lib",
        "mockwebserver",
        "guava",
        "android.app.usage.flags-aconfig-java",
        "android.view.accessibility.flags-aconfig-java",
        "androidx.core_core",
        "androidx.core_core-ktx",
+18 −7
Original line number Diff line number Diff line
@@ -15,24 +15,34 @@
 */
package android.app.usage;

import static android.app.usage.Flags.FLAG_FILTER_BASED_EVENT_QUERY_API;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import android.app.usage.UsageEvents.Event;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Random;
import java.util.Set;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class UsageEventsQueryTest {
    @Rule
    public final CheckFlagsRule mCheckFlagsRule =
            DeviceFlagsValueProvider.createCheckFlagsRule();

    @Test
    @RequiresFlagsEnabled(FLAG_FILTER_BASED_EVENT_QUERY_API)
    public void testQueryDuration() {
        // Test with negative beginTimeMillis.
        long beginTimeMillis = -100;
@@ -97,6 +107,7 @@ public class UsageEventsQueryTest {
    }

    @Test
    @RequiresFlagsEnabled(FLAG_FILTER_BASED_EVENT_QUERY_API)
    public void testQueryEventTypes() {
        Random rnd = new Random();
        UsageEventsQuery.Builder queryBuilder = new UsageEventsQuery.Builder(1000, 2000);
@@ -104,7 +115,7 @@ public class UsageEventsQueryTest {
        // Test with invalid event type.
        int eventType = Event.NONE - 1;
        try {
            queryBuilder.addEventTypes(eventType);
            queryBuilder.setEventTypes(eventType);
            fail("Invalid event type: " + eventType);
        } catch (IllegalArgumentException e) {
            // Expected, fall through.
@@ -112,7 +123,7 @@ public class UsageEventsQueryTest {

        eventType = Event.MAX_EVENT_TYPE + 1;
        try {
            queryBuilder.addEventTypes(eventType);
            queryBuilder.setEventTypes(eventType);
            fail("Invalid event type: " + eventType);
        } catch (IllegalArgumentException e) {
            // Expected, fall through.
@@ -121,11 +132,11 @@ public class UsageEventsQueryTest {
        // Test with valid and duplicate event types.
        eventType = rnd.nextInt(Event.MAX_EVENT_TYPE + 1);
        try {
            UsageEventsQuery query = queryBuilder.addEventTypes(eventType, eventType, eventType)
            UsageEventsQuery query = queryBuilder.setEventTypes(eventType, eventType, eventType)
                    .build();
            Set<Integer> eventTypeSet = query.getEventTypes();
            assertEquals(eventTypeSet.size(), 1);
            int type = eventTypeSet.iterator().next();
            final int[] eventTypesArray = query.getEventTypes();
            assertEquals(eventTypesArray.length, 1);
            int type = eventTypesArray[0];
            assertEquals(type, eventType);
        } catch (IllegalArgumentException e) {
            fail("Valid event type: " + eventType);
Loading