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

Commit ae0ef5ea authored by Willie Koomson's avatar Willie Koomson Committed by Android (Google) Code Review
Browse files

Merge changes from topic "impressions" into main

* changes:
  Add AppWidgetManager.queryAppWidgetEvents API
  Use host-driven visibility tracking instead of draw callbacks
parents 25fbdd63 77b81d1d
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -10098,6 +10098,19 @@ package android.app.wallpaper {
package android.appwidget {
  @FlaggedApi("android.appwidget.flags.engagement_metrics") public final class AppWidgetEvent implements android.os.Parcelable {
    method public int describeContents();
    method public int getAppWidgetId();
    method @Nullable public int[] getClickedIds();
    method @NonNull public java.time.Instant getEnd();
    method @Nullable public android.graphics.Rect getPosition();
    method @Nullable public int[] getScrolledIds();
    method @NonNull public java.time.Instant getStart();
    method @NonNull public java.time.Duration getVisibleDuration();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.appwidget.AppWidgetEvent> CREATOR;
  }
  public class AppWidgetHost {
    ctor public AppWidgetHost(android.content.Context, int);
    method public int allocateAppWidgetId();
@@ -10130,6 +10143,8 @@ package android.appwidget {
    method public void setColorResources(@NonNull android.util.SparseIntArray);
    method public void setExecutor(java.util.concurrent.Executor);
    method public void setOnLightBackground(boolean);
    method @FlaggedApi("android.appwidget.flags.engagement_metrics") public void startVisibilityTracking();
    method @FlaggedApi("android.appwidget.flags.engagement_metrics") public void stopVisibilityTracking();
    method public void updateAppWidget(android.widget.RemoteViews);
    method public void updateAppWidgetOptions(android.os.Bundle);
    method @Deprecated public void updateAppWidgetSize(android.os.Bundle, int, int, int, int);
@@ -10153,6 +10168,7 @@ package android.appwidget {
    method @Deprecated public void notifyAppWidgetViewDataChanged(int, int);
    method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
    method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
    method @FlaggedApi("android.appwidget.flags.engagement_metrics") @NonNull public java.util.List<android.appwidget.AppWidgetEvent> queryAppWidgetEvents(long, long);
    method @FlaggedApi("android.appwidget.flags.generated_previews") public void removeWidgetPreview(@NonNull android.content.ComponentName, int);
    method public boolean requestPinAppWidget(@NonNull android.content.ComponentName, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent);
    method @FlaggedApi("android.appwidget.flags.generated_previews") public boolean setWidgetPreview(@NonNull android.content.ComponentName, int, @NonNull android.widget.RemoteViews);
@@ -10171,8 +10187,6 @@ package android.appwidget {
    field public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
    field public static final String ACTION_APPWIDGET_RESTORED = "android.appwidget.action.APPWIDGET_RESTORED";
    field public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EVENT_CATEGORY_APPWIDGET = "android.appwidget";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EVENT_TYPE_WIDGET_INTERACTION = "widget_interaction";
    field public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
    field public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
    field public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
@@ -10182,10 +10196,6 @@ package android.appwidget {
    field public static final String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
    field public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
    field public static final String EXTRA_CUSTOM_INFO = "customInfo";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_CLICKED_VIEWS = "android.appwidget.extra.EVENT_CLICKED_VIEWS";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_DURATION_MS = "android.appwidget.extra.EVENT_DURATION_MS";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_POSITION_RECT = "android.appwidget.extra.EVENT_POSITION_RECT";
    field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_SCROLLED_VIEWS = "android.appwidget.extra.EVENT_SCROLLED_VIEWS";
    field public static final String EXTRA_HOST_ID = "hostId";
    field public static final int INVALID_APPWIDGET_ID = 0; // 0x0
    field public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
@@ -62148,6 +62158,7 @@ package android.widget {
    method public void removeAllViews(@IdRes int);
    method public void setAccessibilityTraversalAfter(@IdRes int, @IdRes int);
    method public void setAccessibilityTraversalBefore(@IdRes int, @IdRes int);
    method @FlaggedApi("android.appwidget.flags.engagement_metrics") public void setAppWidgetEventTag(@IdRes int, int);
    method public void setBitmap(@IdRes int, String, android.graphics.Bitmap);
    method public void setBlendMode(@IdRes int, @NonNull String, @Nullable android.graphics.BlendMode);
    method public void setBoolean(@IdRes int, String, boolean);
@@ -62210,7 +62221,6 @@ package android.widget {
    method public void setTextViewText(@IdRes int, CharSequence);
    method public void setTextViewTextSize(@IdRes int, int, float);
    method public void setUri(@IdRes int, String, android.net.Uri);
    method @FlaggedApi("android.appwidget.flags.engagement_metrics") public void setUsageEventTag(@IdRes int, int);
    method public void setViewLayoutHeight(@IdRes int, float, int);
    method public void setViewLayoutHeightAttr(@IdRes int, @AttrRes int);
    method public void setViewLayoutHeightDimen(@IdRes int, @DimenRes int);
+151 −32
Original line number Diff line number Diff line
@@ -21,30 +21,38 @@ import static android.appwidget.flags.Flags.FLAG_ENGAGEMENT_METRICS;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.ArraySet;

import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;

/**
 * An immutable class that describes the event data for an app widget interaction event.
 *
 * @hide
 */
@FlaggedApi(FLAG_ENGAGEMENT_METRICS)
public class AppWidgetEvent implements Parcelable {
public final class AppWidgetEvent implements Parcelable {
    /**
     * Max number of clicked and scrolled IDs stored per event.
     * @hide
     */
    public static final int MAX_NUM_ITEMS = 10;

    private final int mAppWidgetId;
    private final long mDurationMs;
    @NonNull
    private final Duration mVisibleDuration;
    @NonNull
    private final Instant mStart;
    @NonNull
    private final Instant mEnd;
    @Nullable
    private final Rect mPosition;
    @Nullable
@@ -54,22 +62,42 @@ public class AppWidgetEvent implements Parcelable {

    /**
     * The app widget ID of the widget that generated this event.
     *
     * @see AppWidgetManager#getAppWidgetInfo(int)
     */
    public int getAppWidgetId() {
        return mAppWidgetId;
    }

    /**
     * This contains a long that represents the duration of time in milliseconds during which the
     * widget was visible.
     * Describes the total duration of time during which the widget was visible. This may be
     * different than the event time range (between {@link #getStart()} and {@link #getEnd()} if the
     * widget was hidden and shown multiple times during the event time range.
     */
    public long getDurationMs() {
        return mDurationMs;
    @NonNull
    public Duration getVisibleDuration() {
        return mVisibleDuration;
    }

    /**
     * This rect with describes the global coordinates of the widget at the end of the interaction
     * event.
     * Describes the start of the time range that this event contains data for.
     */
    @NonNull
    public Instant getStart() {
        return mStart;
    }

    /**
     * Describes the end of the time range that this event contains data for.
     */
    @NonNull
    public Instant getEnd() {
        return mEnd;
    }

    /**
     * This rect with describes the global coordinates of the widget at the end of the event time
     * range.
     */
    @Nullable
    public Rect getPosition() {
@@ -77,7 +105,10 @@ public class AppWidgetEvent implements Parcelable {
    }

    /**
     * This describes which views have been clicked during a single impression of the widget.
     * This returns the set of View IDs of the views which have been clicked during the event time
     * range. Use {@link android.widget.RemoteViews#setAppWidgetEventTag(int, int)} to set a custom
     * integer tag on a view for reporting clicks. If the tag is set, it will be used here instead
     * of the View ID.
     */
    @Nullable
    public int[] getClickedIds() {
@@ -85,18 +116,23 @@ public class AppWidgetEvent implements Parcelable {
    }

    /**
     * This describes which views have been scrolled during a single impression of the widget.
     * This returns the set of View IDs of the views which have been scrolled during the event time
     * range. Use {@link android.widget.RemoteViews#setAppWidgetEventTag(int, int)} to set a custom
     * integer tag on a view for reporting scrolls. If the tag is set, it will be used here instead
     * of the View ID.
     */
    @Nullable
    public int[] getScrolledIds() {
        return mScrolledIds;
    }

    private AppWidgetEvent(int appWidgetId, long durationMs,
            @Nullable Rect position, @Nullable int[] clickedIds,
            @Nullable int[] scrolledIds) {
    private AppWidgetEvent(int appWidgetId, @NonNull Duration visibleDuration,
            @NonNull Instant start, @NonNull Instant end, @Nullable Rect position,
            @Nullable int[] clickedIds, @Nullable int[] scrolledIds) {
        mAppWidgetId = appWidgetId;
        mDurationMs = durationMs;
        mVisibleDuration = visibleDuration;
        mStart = start;
        mEnd = end;
        mPosition = position;
        mClickedIds = clickedIds;
        mScrolledIds = scrolledIds;
@@ -105,18 +141,22 @@ public class AppWidgetEvent implements Parcelable {
    /**
     * Unflatten the AppWidgetEvent from a parcel.
     */
    private AppWidgetEvent(Parcel in) {
    private AppWidgetEvent(@NonNull Parcel in) {
        mAppWidgetId = in.readInt();
        mDurationMs = in.readLong();
        mVisibleDuration = Duration.ofMillis(in.readLong());
        mStart = Instant.ofEpochMilli(in.readLong());
        mEnd = Instant.ofEpochMilli(in.readLong());
        mPosition = in.readTypedObject(Rect.CREATOR);
        mClickedIds = in.createIntArray();
        mScrolledIds = in.createIntArray();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
    public void writeToParcel(@NonNull Parcel out, int flags) {
        out.writeInt(mAppWidgetId);
        out.writeLong(mDurationMs);
        out.writeLong(mVisibleDuration.toMillis());
        out.writeLong(mStart.toEpochMilli());
        out.writeLong(mEnd.toEpochMilli());
        out.writeTypedObject(mPosition, flags);
        out.writeIntArray(mClickedIds);
        out.writeIntArray(mScrolledIds);
@@ -143,6 +183,7 @@ public class AppWidgetEvent implements Parcelable {

    /**
     * Create a PersistableBundle that represents this event.
     * @hide
     */
    @NonNull
    public PersistableBundle toBundle() {
@@ -152,7 +193,9 @@ public class AppWidgetEvent implements Parcelable {
        extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY,
                AppWidgetManager.EVENT_CATEGORY_APPWIDGET);
        extras.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
        extras.putLong(AppWidgetManager.EXTRA_EVENT_DURATION_MS, mDurationMs);
        extras.putLong(AppWidgetManager.EXTRA_EVENT_DURATION_MS, mVisibleDuration.toMillis());
        extras.putLong(AppWidgetManager.EXTRA_EVENT_START, mStart.toEpochMilli());
        extras.putLong(AppWidgetManager.EXTRA_EVENT_END, mEnd.toEpochMilli());
        if (mPosition != null) {
            extras.putIntArray(AppWidgetManager.EXTRA_EVENT_POSITION_RECT,
                new int[]{mPosition.left, mPosition.top, mPosition.right, mPosition.bottom});
@@ -166,11 +209,56 @@ public class AppWidgetEvent implements Parcelable {
        return extras;
    }

    /**
     * Create an AppWidgetEvent from a {@link UsageEvents.Event}.
     * @hide
     */
    @NonNull
    public static AppWidgetEvent fromUsageEvent(@NonNull UsageEvents.Event usageEvent) {
        PersistableBundle extras = usageEvent.getExtras();
        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
        Duration duration = Duration.ofMillis(extras.getLong(
                AppWidgetManager.EXTRA_EVENT_DURATION_MS, 0L));
        Instant start = Instant.ofEpochMilli(extras.getLong(AppWidgetManager.EXTRA_EVENT_START,
                0L));
        Instant end = Instant.ofEpochMilli(extras.getLong(AppWidgetManager.EXTRA_EVENT_END, 0L));
        Rect position = null;
        int[] clickedIds = null;
        int[] scrolledIds = null;
        if (extras.containsKey(AppWidgetManager.EXTRA_EVENT_POSITION_RECT)) {
            int[] positionArray = extras.getIntArray(AppWidgetManager.EXTRA_EVENT_POSITION_RECT);
            if (positionArray != null && positionArray.length == 4) {
                position = new Rect(positionArray[0], positionArray[1], positionArray[2],
                        positionArray[3]);
            }
        }
        if (extras.containsKey(AppWidgetManager.EXTRA_EVENT_CLICKED_VIEWS)) {
            clickedIds = extras.getIntArray(AppWidgetManager.EXTRA_EVENT_CLICKED_VIEWS);
        }
        if (extras.containsKey(AppWidgetManager.EXTRA_EVENT_SCROLLED_VIEWS)) {
            scrolledIds = extras.getIntArray(AppWidgetManager.EXTRA_EVENT_SCROLLED_VIEWS);
        }
        return new AppWidgetEvent(appWidgetId, duration, start, end, position, clickedIds,
            scrolledIds);
    }

    @Override
    public String toString() {
        return TextUtils.formatSimple("AppWidgetEvent(appWidgetId=%d, durationMs=%d, position=%s,"
                + " clickedIds=%s, scrolledIds=%s)", mAppWidgetId, mDurationMs, mPosition,
            Arrays.toString(mClickedIds), Arrays.toString(mScrolledIds));
        return TextUtils.formatSimple("AppWidgetEvent(appWidgetId=%d, duration=%s, start=%s, "
                + "end=%s position=%s, clickedIds=%s, scrolledIds=%s)", mAppWidgetId,
            mVisibleDuration, mStart, mEnd, mPosition, Arrays.toString(mClickedIds),
            Arrays.toString(mScrolledIds));
    }

    /**
     * Returns true if the given {@link UsageEvents.Event} contains an app widget interaction event.
     * @hide
     */
    public static boolean isAppWidgetEvent(@NonNull UsageEvents.Event event) {
        return event.getEventType() == UsageEvents.Event.USER_INTERACTION
            && event.getExtras().getString(UsageStatsManager.EXTRA_EVENT_ACTION).equals(
                AppWidgetManager.EVENT_TYPE_WIDGET_INTERACTION);
    }

    /**
@@ -184,7 +272,10 @@ public class AppWidgetEvent implements Parcelable {
        @NonNull
        private final ArraySet<Integer> mScrolledIds = new ArraySet<>(MAX_NUM_ITEMS);
        private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
        private long mDurationMs = 0;
        private Instant mStart = Instant.MAX;
        private Instant mEnd = Instant.MIN;
        private Duration mDuration = Duration.ZERO;
        private long mLastVisibilityChangeMillis = 0L;
        @Nullable
        private Rect mPosition = null;

@@ -196,8 +287,28 @@ public class AppWidgetEvent implements Parcelable {
            return this;
        }

        public Builder addDurationMs(long durationMs) {
            mDurationMs += durationMs;
        /**
         * Start a new visibility duration for this event.
         */
        public Builder startVisibility() {
            Instant now = Instant.now();
            if (now.isBefore(mStart)) {
                mStart = now;
            }
            mLastVisibilityChangeMillis = SystemClock.uptimeMillis();
            return this;
        }

        /**
         * End the visibility duration, and add the duration to this event's total duration.
         */
        public Builder endVisibility() {
            Instant now = Instant.now();
            if (now.isAfter(mEnd)) {
                mEnd = now;
            }
            mDuration = mDuration.plusMillis(
                SystemClock.uptimeMillis() - mLastVisibilityChangeMillis);
            return this;
        }

@@ -234,7 +345,13 @@ public class AppWidgetEvent implements Parcelable {
                throw new IllegalArgumentException("Trying to merge events with different app "
                    + "widget IDs: " + mAppWidgetId + " != " + event.getAppWidgetId());
            }
            addDurationMs(event.getDurationMs());
            if (event.getStart().isBefore(mStart)) {
                mStart = event.getStart();
            }
            if (event.getEnd().isAfter(mEnd)) {
                mEnd = event.getEnd();
            }
            mDuration = mDuration.plus(event.getVisibleDuration());
            setPosition(event.getPosition());
            addAllUntilMax(mClickedIds, event.getClickedIds());
            addAllUntilMax(mScrolledIds, event.getScrolledIds());
@@ -245,22 +362,24 @@ public class AppWidgetEvent implements Parcelable {
         * event yet.
         */
        public boolean isEmpty() {
            return mAppWidgetId <= 0 || mDurationMs == 0L;
            return mAppWidgetId <= 0 || mDuration.isZero();
        }

        /**
         * Resets the event data fields.
         */
        public void clear() {
            mDurationMs = 0;
            mDuration = Duration.ZERO;
            mStart = Instant.MAX;
            mEnd = Instant.MIN;
            mPosition = null;
            mClickedIds.clear();
            mScrolledIds.clear();
        }

        public AppWidgetEvent build() {
            return new AppWidgetEvent(mAppWidgetId, mDurationMs, mPosition, toIntArray(mClickedIds),
                toIntArray(mScrolledIds));
            return new AppWidgetEvent(mAppWidgetId, mDuration, mStart, mEnd, mPosition,
                    toIntArray(mClickedIds), toIntArray(mScrolledIds));
        }

        private static void addAllUntilMax(@NonNull ArraySet<Integer> set, @Nullable int[] toAdd) {
+28 −32
Original line number Diff line number Diff line
@@ -674,7 +674,6 @@ public class AppWidgetHost {
        }

        List<AppWidgetEvent> eventList = new ArrayList<>();
        mMainHandler.post(() -> {
        synchronized (mListeners) {
            for (int i = 0; i < mListeners.size(); i++) {
                AppWidgetEvent event = mListeners.valueAt(i).collectWidgetEvent();
@@ -696,7 +695,6 @@ public class AppWidgetHost {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        });
    }

    /**
@@ -712,7 +710,6 @@ public class AppWidgetHost {
        if (listener == null) {
            return;
        }
        mMainHandler.post(() -> {
        AppWidgetEvent event = listener.collectWidgetEvent();
        if (event == null) {
            return;
@@ -724,7 +721,6 @@ public class AppWidgetHost {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        });
    }
}

+103 −67

File changed.

Preview size limit exceeded, changes collapsed.

+55 −9
Original line number Diff line number Diff line
@@ -499,13 +499,15 @@ public class AppWidgetManager {
     *
     * A single widget interaction event describes what user interactions happened during a single
     * impression of the widget.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EVENT_TYPE_WIDGET_INTERACTION = "widget_interaction";
    static final String EVENT_TYPE_WIDGET_INTERACTION = "widget_interaction";

    /**
     * This is the value of {@link UsageStatsManager.EXTRA_EVENT_CATEGORY} in the event bundle for
     * widget user interaction events.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EVENT_CATEGORY_APPWIDGET = "android.appwidget";
@@ -516,12 +518,13 @@ public class AppWidgetManager {
     * 10 distinct IDs per event.
     *
     * Widget providers may set a different ID for event logging by setting the usage event tag on
     * the view with {@link RemoteViews#setUsageEventTag}.
     * the view with {@link RemoteViews#setAppWidgetEventTag}.
     *
     * @see android.widget.RemoteViews#setUsageEventTag
     * @see android.widget.RemoteViews#setAppWidgetEventTag
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EXTRA_EVENT_CLICKED_VIEWS =
    static final String EXTRA_EVENT_CLICKED_VIEWS =
            "android.appwidget.extra.EVENT_CLICKED_VIEWS";

    /**
@@ -530,20 +533,22 @@ public class AppWidgetManager {
     * 10 distinct IDs per event.
     *
     * Widget providers may set a different ID for event logging by setting the usage event tag on
     * the view with {@link RemoteViews#setUsageEventTag}.
     * the view with {@link RemoteViews#setAppWidgetEventTag}.
     *
     * @see android.widget.RemoteViews#setUsageEventTag
     * @see android.widget.RemoteViews#setAppWidgetEventTag
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EXTRA_EVENT_SCROLLED_VIEWS =
    static final String EXTRA_EVENT_SCROLLED_VIEWS =
            "android.appwidget.extra.EVENT_SCROLLED_VIEWS";

    /**
     * This bundle extra contains a long that represents the duration of time in milliseconds
     * during which the widget was visible.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EXTRA_EVENT_DURATION_MS =
    static final String EXTRA_EVENT_DURATION_MS =
            "android.appwidget.extra.EVENT_DURATION_MS";

    /**
@@ -551,11 +556,28 @@ public class AppWidgetManager {
     * right, and bottom coordinates of the widget at the end of the interaction event.
     *
     * This Rect indicates the current position and size of the widget.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    public static final String EXTRA_EVENT_POSITION_RECT =
    static final String EXTRA_EVENT_POSITION_RECT =
            "android.appwidget.extra.EVENT_POSITION_RECT";

    /**
     * This bundle extra contains a long that describes the start (in epoch milliseconds) of the
     * time range that this event represents.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    static final String EXTRA_EVENT_START = "android.appwidget.extra.EVENT_START";

    /**
     * This bundle extra contains a long that describes the end (in epoch milliseconds) of the time
     * range that this event represents.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    static final String EXTRA_EVENT_END = "android.appwidget.extra.EVENT_END";

    private static final String TAG = "AppWidgetManager";

    private static Executor sUpdateExecutor;
@@ -1642,6 +1664,30 @@ public class AppWidgetManager {
        }
    }

    /**
     * Query for app widget interaction events in the given time range. Events are only kept by the
     * system for a few days. This method only returns events for widgets provided by the calling
     * package and does not require any additional permissions.
     *
     * @param beginTime The inclusive beginning of the range of events to include in the results.
     *                  Defined in terms of "Unix time", see
     *                  {@link java.lang.System#currentTimeMillis}.
     * @param endTime The exclusive end of the range of events to include in the results. Defined
     *                in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}.
     * @return An array of {@link AppWidgetEvent} objects.
     */
    @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS)
    @NonNull
    public List<AppWidgetEvent> queryAppWidgetEvents(long beginTime, long endTime) {
        try {
            ParceledListSlice<AppWidgetEvent> events = mService.queryAppWidgetEvents(mPackageName,
                    beginTime, endTime);
            return events != null ? events.getList() : Collections.emptyList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @UiThread
    private static @NonNull Executor createUpdateExecutorIfNull() {
        if (sUpdateExecutor == null) {
Loading