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

Commit 2857f1c7 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Changing startListening to only fetch views which are bound

Also associating a lastUpdateTime with every widget. This allows
the host to query the widgets which were updated only after
the last stopListening call.

Change-Id: If9375cf2d8caa0ccca14b6649821d87ada1f3a84
parent 08f41dfb
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -17,8 +17,7 @@
package android.appwidget;

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

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,7 +34,9 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.util.TypedValue;
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
@@ -62,7 +63,7 @@ public class AppWidgetHost {
    private final Handler mHandler;
    private final int mHostId;
    private final Callbacks mCallbacks;
    private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
    private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
    private OnClickHandler mOnClickHandler;

    static class Callbacks extends IAppWidgetHost.Stub {
@@ -164,7 +165,6 @@ public class AppWidgetHost {
        bindService();
    }


    private static void bindService() {
        synchronized (sServiceLock) {
            if (sService == null) {
@@ -179,17 +179,25 @@ public class AppWidgetHost {
     * becomes visible, i.e. from onStart() in your Activity.
     */
    public void startListening() {
        int[] updatedIds;
        ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
        final int[] idsToUpdate;
        synchronized (mViews) {
            int N = mViews.size();
            idsToUpdate = new int[N];
            for (int i = 0; i < N; i++) {
                idsToUpdate[i] = mViews.keyAt(i);
            }
        }
        List<RemoteViews> updatedViews;
        int[] updatedIds = new int[idsToUpdate.length];
        try {
            updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
                    updatedViews);
            updatedViews = sService.startListening(
                    mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList();
        }
        catch (RemoteException e) {
            throw new RuntimeException("system server dead?", e);
        }

        final int N = updatedIds.length;
        int N = updatedViews.size();
        for (int i = 0; i < N; i++) {
            updateAppWidgetView(updatedIds[i], updatedViews.get(i));
        }
@@ -206,10 +214,6 @@ public class AppWidgetHost {
        catch (RemoteException e) {
            throw new RuntimeException("system server dead?", e);
        }

        // This is here because keyguard needs it since it'll be switching users after this call.
        // If it turns out other apps need to call this often, we should re-think how this works.
        clearViews();
    }

    /**
@@ -418,8 +422,10 @@ public class AppWidgetHost {
     * Clear the list of Views that have been created by this AppWidgetHost.
     */
    protected void clearViews() {
        synchronized (mViews) {
            mViews.clear();
        }
    }
}

+2 −2
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ interface IAppWidgetService {
    //
    // for AppWidgetHost
    //
    int[] startListening(IAppWidgetHost host, String callingPackage, int hostId,
            out List<RemoteViews> updatedViews);
    ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId,
            in int[] appWidgetIds, out int[] updatedIds);
    void stopListening(String callingPackage, int hostId);
    int allocateAppWidgetId(String callingPackage, int hostId);
    void deleteAppWidgetId(String callingPackage, int appWidgetId);
+41 −15
Original line number Diff line number Diff line
@@ -742,8 +742,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    @Override
    public int[] startListening(IAppWidgetHost callbacks, String callingPackage,
            int hostId, List<RemoteViews> updatedViews) {
    public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
            String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
        final int userId = UserHandle.getCallingUserId();

        if (DEBUG) {
@@ -760,21 +760,21 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            // sure the caller can only access hosts it owns.
            HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
            Host host = lookupOrAddHostLocked(id);

            host.callbacks = callbacks;

            updatedViews.clear();

            ArrayList<Widget> instances = host.widgets;
            int N = instances.size();
            int[] updatedIds = new int[N];
            int N = appWidgetIds.length;
            ArrayList<RemoteViews> outViews = new ArrayList<>(N);
            RemoteViews rv;
            int added = 0;
            for (int i = 0; i < N; i++) {
                Widget widget = instances.get(i);
                updatedIds[i] = widget.appWidgetId;
                updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
                rv = host.getPendingViewsForId(appWidgetIds[i]);
                if (rv != null) {
                    updatedIds[added] = appWidgetIds[i];
                    outViews.add(rv);
                    added++;
                }

            return updatedIds;
            }
            return new ParceledListSlice<>(outViews);
        }
    }

@@ -1882,6 +1882,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
        long requestTime = SystemClock.uptimeMillis();
        if (widget != null) {
            widget.lastUpdateTime = requestTime;
        }
        if (widget == null || widget.provider == null || widget.provider.zombie
                || widget.host.callbacks == null || widget.host.zombie) {
            return;
@@ -1891,6 +1895,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        args.arg1 = widget.host;
        args.arg2 = widget.host.callbacks;
        args.arg3 = updateViews;
        args.arg4 = requestTime;
        args.argi1 = widget.appWidgetId;

        mCallbackHandler.obtainMessage(
@@ -1899,9 +1904,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }

    private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
            int appWidgetId, RemoteViews views) {
            int appWidgetId, RemoteViews views, long requestTime) {
        try {
            callbacks.updateAppWidget(appWidgetId, views);
            host.lastWidgetUpdateTime = requestTime;
        } catch (RemoteException re) {
            synchronized (mLock) {
                Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3398,10 +3404,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                    Host host = (Host) args.arg1;
                    IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
                    RemoteViews views = (RemoteViews) args.arg3;
                    long requestTime = (Long) args.arg4;
                    final int appWidgetId = args.argi1;
                    args.recycle();

                    handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views);
                    handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
                } break;

                case MSG_NOTIFY_PROVIDER_CHANGED: {
@@ -3769,6 +3776,7 @@ 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 lastWidgetUpdateTime; // last time we were successfully able to send an update.

        public int getUserId() {
            return UserHandle.getUserId(id.uid);
@@ -3790,6 +3798,23 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            return false;
        }

        /**
         * Returns the RemoveViews for the provided widget id if an update is pending
         * for that widget.
         */
        public RemoteViews getPendingViewsForId(int appWidgetId) {
            long updateTime = lastWidgetUpdateTime;
            int N = widgets.size();
            for (int i = 0; i < N; i++) {
                Widget widget = widgets.get(i);
                if (widget.appWidgetId == appWidgetId
                        && widget.lastUpdateTime > updateTime) {
                    return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
                }
            }
            return null;
        }

        @Override
        public String toString() {
            return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -3860,6 +3885,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        RemoteViews maskedViews;
        Bundle options;
        Host host;
        long lastUpdateTime;

        @Override
        public String toString() {