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

Commit 67b00a04 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Fixing same pending update being sent every time startListening is called

if there was no widget update in-between

Bug: 67736800
Test: Added corresponding test in AppWidgetServiceImplTest
Change-Id: Ib3213f8f79ac11ed05b317e25110d7e37561b837
parent 1a64682c
Loading
Loading
Loading
Loading
+28 −21
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.service.appwidget.AppWidgetServiceDumpProto;
import android.service.appwidget.WidgetProto;
import android.text.TextUtils;
@@ -159,7 +158,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    // Bump if the stored widgets need to be upgraded.
    private static final int CURRENT_VERSION = 1;

    private static final AtomicLong REQUEST_COUNTER = new AtomicLong();
    // Every widget update request is associated which an increasing sequence number. This is
    // used to verify which request has successfully been received by the host.
    private static final AtomicLong UPDATE_COUNTER = new AtomicLong();

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
@@ -814,9 +815,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            Host host = lookupOrAddHostLocked(id);
            host.callbacks = callbacks;

            long updateSequenceNo = UPDATE_COUNTER.incrementAndGet();
            int N = appWidgetIds.length;
            ArrayList<PendingHostUpdate> outUpdates = new ArrayList<>(N);

            LongSparseArray<PendingHostUpdate> updatesMap = new LongSparseArray<>();
            for (int i = 0; i < N; i++) {
                if (host.getPendingUpdatesForId(appWidgetIds[i], updatesMap)) {
@@ -828,6 +829,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                    }
                }
            }
            // Reset the update counter once all the updates have been calculated
            host.lastWidgetUpdateSequenceNo = updateSequenceNo;
            return new ParceledListSlice<>(outUpdates);
        }
    }
@@ -1914,9 +1917,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            // method with a wrong id. In that case, ignore the call.
            return;
        }
        long requestId = REQUEST_COUNTER.incrementAndGet();
        long requestId = UPDATE_COUNTER.incrementAndGet();
        if (widget != null) {
            widget.updateRequestIds.put(viewId, requestId);
            widget.updateSequenceNos.put(viewId, requestId);
        }
        if (widget == null || widget.host == null || widget.host.zombie
                || widget.host.callbacks == null || widget.provider == null
@@ -1941,7 +1944,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            int appWidgetId, int viewId, long requestId) {
        try {
            callbacks.viewDataChanged(appWidgetId, viewId);
            host.lastWidgetUpdateRequestId = requestId;
            host.lastWidgetUpdateSequenceNo = requestId;
        } catch (RemoteException re) {
            // It failed; remove the callback. No need to prune because
            // we know that this host is still referenced by this instance.
@@ -1988,9 +1991,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
        long requestId = REQUEST_COUNTER.incrementAndGet();
        long requestId = UPDATE_COUNTER.incrementAndGet();
        if (widget != null) {
            widget.updateRequestIds.put(ID_VIEWS_UPDATE, requestId);
            widget.updateSequenceNos.put(ID_VIEWS_UPDATE, requestId);
        }
        if (widget == null || widget.provider == null || widget.provider.zombie
                || widget.host.callbacks == null || widget.host.zombie) {
@@ -2013,7 +2016,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            int appWidgetId, RemoteViews views, long requestId) {
        try {
            callbacks.updateAppWidget(appWidgetId, views);
            host.lastWidgetUpdateRequestId = requestId;
            host.lastWidgetUpdateSequenceNo = requestId;
        } catch (RemoteException re) {
            synchronized (mLock) {
                Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -2023,11 +2026,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    private void scheduleNotifyProviderChangedLocked(Widget widget) {
        long requestId = REQUEST_COUNTER.incrementAndGet();
        long requestId = UPDATE_COUNTER.incrementAndGet();
        if (widget != null) {
            // When the provider changes, reset everything else.
            widget.updateRequestIds.clear();
            widget.updateRequestIds.append(ID_PROVIDER_CHANGED, requestId);
            widget.updateSequenceNos.clear();
            widget.updateSequenceNos.append(ID_PROVIDER_CHANGED, requestId);
        }
        if (widget == null || widget.provider == null || widget.provider.zombie
                || widget.host.callbacks == null || widget.host.zombie) {
@@ -2050,7 +2053,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            int appWidgetId, AppWidgetProviderInfo info, long requestId) {
        try {
            callbacks.providerChanged(appWidgetId, info);
            host.lastWidgetUpdateRequestId = requestId;
            host.lastWidgetUpdateSequenceNo = requestId;
        } catch (RemoteException re) {
            synchronized (mLock){
                Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3887,7 +3890,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it

        int tag = TAG_UNDEFINED; // for use while saving state (the index)
        long lastWidgetUpdateRequestId; // request id for the last update successfully sent
        // Sequence no for the last update successfully sent. This is updated whenever a
        // widget update is successfully sent to the host callbacks. As all new/undelivered updates
        // will have sequenceNo greater than this, all those updates will be sent when the host
        // callbacks are attached again.
        long lastWidgetUpdateSequenceNo;

        public int getUserId() {
            return UserHandle.getUserId(id.uid);
@@ -3914,18 +3921,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
         */
        public boolean getPendingUpdatesForId(int appWidgetId,
                LongSparseArray<PendingHostUpdate> outUpdates) {
            long updateRequestId = lastWidgetUpdateRequestId;
            long updateSequenceNo = lastWidgetUpdateSequenceNo;
            int N = widgets.size();
            for (int i = 0; i < N; i++) {
                Widget widget = widgets.get(i);
                if (widget.appWidgetId == appWidgetId) {
                    outUpdates.clear();
                    for (int j = widget.updateRequestIds.size() - 1; j >= 0; j--) {
                        long requestId = widget.updateRequestIds.valueAt(j);
                        if (requestId <= updateRequestId) {
                    for (int j = widget.updateSequenceNos.size() - 1; j >= 0; j--) {
                        long requestId = widget.updateSequenceNos.valueAt(j);
                        if (requestId <= updateSequenceNo) {
                            continue;
                        }
                        int id = widget.updateRequestIds.keyAt(j);
                        int id = widget.updateSequenceNos.keyAt(j);
                        final PendingHostUpdate update;
                        switch (id) {
                            case ID_PROVIDER_CHANGED:
@@ -4021,8 +4028,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        RemoteViews maskedViews;
        Bundle options;
        Host host;
        // Request ids for various operations
        SparseLongArray updateRequestIds = new SparseLongArray(2);
        // Map of request type to updateSequenceNo.
        SparseLongArray updateSequenceNos = new SparseLongArray(2);

        @Override
        public String toString() {
+20 −0
Original line number Diff line number Diff line
@@ -247,6 +247,26 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase {
        assertEquals(7, updates.size());
    }

    public void testUpdatesReceived_queueEmptyAfterStartListening() {
        int widgetId = setupHostAndWidget();
        int widgetId2 = bindNewWidget();
        mService.stopListening(mPkgName, HOST_ID);

        sendDummyUpdates(widgetId, 22, 23);
        sendDummyUpdates(widgetId2, 100, 101, 102);

        List<PendingHostUpdate> updates = mService.startListening(
                mMockHost, mPkgName, HOST_ID, new int[]{widgetId, widgetId2}).getList();
        // 3 updates for first widget and 4 for second
        assertEquals(7, updates.size());

        // Stop and start listening again
        mService.stopListening(mPkgName, HOST_ID);
        updates = mService.startListening(
                mMockHost, mPkgName, HOST_ID, new int[]{widgetId, widgetId2}).getList();
        assertTrue(updates.isEmpty());
    }

    public void testGetInstalledProvidersForPackage() {
        List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
        assertTrue(!allProviders.isEmpty());