diff options
| author | 2016-04-05 18:53:17 +0000 | |
|---|---|---|
| committer | 2016-04-05 18:53:18 +0000 | |
| commit | 60c74e836fc40d65c8ac58c231956f57d26ec7eb (patch) | |
| tree | 9bb694576d32bee11087f371e67a60d8239accb2 | |
| parent | 0c9d1b06c3f9830264623ad2c8842db6d47809d3 (diff) | |
| parent | 2857f1c783e69461735a51159f9abdb85378e210 (diff) | |
Merge "Changing startListening to only fetch views which are bound" into nyc-dev
3 files changed, 63 insertions, 31 deletions
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 1af495365825..2d9f4a71b005 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -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,7 +422,9 @@ public class AppWidgetHost { * Clear the list of Views that have been created by this AppWidgetHost. */ protected void clearViews() { - mViews.clear(); + synchronized (mViews) { + mViews.clear(); + } } } diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index 5a195cb7dd20..4260e50a31f2 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -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); diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index b6a99c8bdcf7..1b0d3acb1bad 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -744,8 +744,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) { @@ -762,21 +762,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); } } @@ -1884,6 +1884,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; @@ -1893,6 +1897,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( @@ -1901,9 +1906,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); @@ -3400,10 +3406,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: { @@ -3771,6 +3778,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); @@ -3792,6 +3800,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" : "") + '}'; @@ -3862,6 +3887,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku RemoteViews maskedViews; Bundle options; Host host; + long lastUpdateTime; @Override public String toString() { |