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

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

Merge "Report widget interaction events" into main

parents 2ebf55f5 6d29ba06
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -45,6 +46,7 @@ import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
@@ -286,6 +288,7 @@ public class AppWidgetHost {
        catch (RemoteException e) {
            throw new RuntimeException("system server dead?", e);
        }
        reportAllWidgetEvents();
    }

    /**
@@ -384,6 +387,7 @@ public class AppWidgetHost {
        } catch (RemoteException e) {
            throw new RuntimeException("System server dead?", e);
        }
        reportAllWidgetEvents();
    }

    /**
@@ -554,6 +558,16 @@ public class AppWidgetHost {
         * @hide
         */
        void onViewDataChanged(int viewId);

        /**
         * This function returns the current set of widget event data being tracked by this widget.
         *
         * @hide
         */
        @Nullable
        default PersistableBundle collectWidgetEvent() {
            return null;
        }
    }

    void dispatchOnAppWidgetRemoved(int appWidgetId) {
@@ -604,6 +618,7 @@ public class AppWidgetHost {
     * @hide
     */
    public void removeListener(int appWidgetId) {
        reportEventForWidget(appWidgetId);
        synchronized (mListeners) {
            mListeners.remove(appWidgetId);
        }
@@ -636,10 +651,71 @@ public class AppWidgetHost {
     * Clear the list of Views that have been created by this AppWidgetHost.
     */
    protected void clearViews() {
        reportAllWidgetEvents();
        synchronized (mListeners) {
            mListeners.clear();
        }
    }

    /**
     * Report any pending widget event data to the AppWidgetService.
     *
     * @hide
     */
    public void reportAllWidgetEvents() {
        if (sService == null) {
            return;
        }

        List<PersistableBundle> eventList = new ArrayList<>();
        synchronized (mListeners) {
            for (int i = 0; i < mListeners.size(); i++) {
                PersistableBundle event = mListeners.valueAt(i).collectWidgetEvent();
                if (event != null) {
                    eventList.add(event);
                }
            }
        }
        if (eventList.isEmpty()) {
            return;
        }
        PersistableBundle[] events = new PersistableBundle[eventList.size()];
        for (int i = 0; i < events.length; i++) {
            events[i] = eventList.get(i);
        }

        try {
            sService.reportWidgetEvents(mContextOpPackageName, events);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Report a pending widget event to the AppWidgetService.
     *
     * @hide
     */
    public void reportEventForWidget(int appWidgetId) {
        if (sService == null) {
            return;
        }
        AppWidgetHostListener listener = getListener(appWidgetId);
        if (listener == null) {
            return;
        }
        PersistableBundle event = listener.collectWidgetEvent();
        if (event == null) {
            return;
        }
        PersistableBundle[] events = {event};

        try {
            sService.reportWidgetEvents(mContextOpPackageName, events);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

+43 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -1041,6 +1042,17 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
        }
    }

    /**
     * This function returns the current set of widget event data being tracked by this widget. The
     * tracked data is cleared is returned here.
     *
     * @hide
     */
    @Override
    public PersistableBundle collectWidgetEvent() {
        return mInteractionLogger.collectWidgetEvent();
    }

    /**
     * This class is used to track user interactions with this widget.
     * @hide
@@ -1052,10 +1064,10 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
        private static final long UPDATE_VISIBILITY_DELAY_MS = 1000L;
        // Clicked views
        @NonNull
        private final Set<Integer> mClickedIds = new ArraySet<>(MAX_NUM_ITEMS);
        private final ArraySet<Integer> mClickedIds = new ArraySet<>(MAX_NUM_ITEMS);
        // Scrolled views
        @NonNull
        private final Set<Integer> mScrolledIds = new ArraySet<>(MAX_NUM_ITEMS);
        private final ArraySet<Integer> mScrolledIds = new ArraySet<>(MAX_NUM_ITEMS);
        @Nullable
        private RemoteViews.InteractionHandler mInteractionHandler = null;
        // Last position this widget was laid out in
@@ -1229,6 +1241,35 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
            return view.isAggregatedVisible() && view.getGlobalVisibleRect(new Rect())
                    && view.getAlpha() != 0;
        }

        @Nullable
        private PersistableBundle collectWidgetEvent() {
            if (mIsVisible) {
                // If the widget is currently visible, add the current duration to the event data.
                updateVisibility(false);
            }
            if (mAppWidgetId <= 0 || mDurationMs == 0L) {
                return null;
            }
            PersistableBundle event = AppWidgetManager.createWidgetInteractionEvent(mAppWidgetId,
                    mDurationMs, mPosition, toIntArray(mClickedIds), toIntArray(mScrolledIds));

            mClickedIds.clear();
            mScrolledIds.clear();
            mDurationMs = 0;
            mPosition = null;

            return event;
        }

        private static int[] toIntArray(ArraySet<Integer> set) {
            if (set.isEmpty()) return null;
            int[] array = new int[set.size()];
            for (int i = 0; i < array.length; i++) {
                array[i] = set.valueAt(i);
            }
            return array;
        }
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -1626,7 +1626,6 @@ public class AppWidgetManager {
        return extras;
    }


    @UiThread
    private static @NonNull Executor createUpdateExecutorIfNull() {
        if (sUpdateExecutor == null) {
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.pm.ParceledListSlice;
import android.appwidget.AppWidgetProviderInfo;
import com.android.internal.appwidget.IAppWidgetHost;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.IBinder;
import android.widget.RemoteViews;
import android.app.IApplicationThread;
@@ -86,5 +87,6 @@ interface IAppWidgetService {
    @nullable RemoteViews getWidgetPreview(in String callingPackage,
            in ComponentName providerComponent, in int profileId, in int widgetCategory);
    void removeWidgetPreview(in ComponentName providerComponent, in int widgetCategories);
    oneway void reportWidgetEvents(in String callingPackage, in PersistableBundle[] events);
}
+6 −0
Original line number Diff line number Diff line
@@ -579,6 +579,12 @@ public final class SystemUiDeviceConfigFlags {
    public static final String GENERATED_PREVIEW_API_MAX_PROVIDERS =
            "generated_preview_api_max_providers";

    /**
     * (long) The bucket interval for reporting widget interaction events to UsageStatsManager.
     */
    public static final String WIDGET_EVENTS_REPORT_INTERVAL_MS =
            "widget_events_report_interval_ms";

    private SystemUiDeviceConfigFlags() {
    }
}
Loading