Loading core/java/android/appwidget/AppWidgetHost.java +46 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; import android.widget.RemoteViews; import android.widget.RemoteViews.InteractionHandler; Loading @@ -52,12 +53,15 @@ import java.util.List; */ public class AppWidgetHost { private static final String TAG = "AppWidgetHost"; static final int HANDLE_UPDATE = 1; static final int HANDLE_PROVIDER_CHANGED = 2; static final int HANDLE_PROVIDERS_CHANGED = 3; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) static final int HANDLE_VIEW_DATA_CHANGED = 4; static final int HANDLE_APP_WIDGET_REMOVED = 5; static final int HANDLE_VIEW_UPDATE_DEFERRED = 6; final static Object sServiceLock = new Object(); @UnsupportedAppUsage Loading Loading @@ -131,6 +135,15 @@ public class AppWidgetHost { msg.sendToTarget(); } public void updateAppWidgetDeferred(int appWidgetId) { Handler handler = mWeakHandler.get(); if (handler == null) { return; } Message msg = handler.obtainMessage(HANDLE_VIEW_UPDATE_DEFERRED, appWidgetId, 0, null); msg.sendToTarget(); } private static boolean isLocalBinder() { return Process.myPid() == Binder.getCallingPid(); } Loading Loading @@ -163,6 +176,10 @@ public class AppWidgetHost { viewDataChanged(msg.arg1, msg.arg2); break; } case HANDLE_VIEW_UPDATE_DEFERRED: { updateAppWidgetDeferred(msg.arg1); break; } } } } Loading Loading @@ -480,13 +497,31 @@ public class AppWidgetHost { void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo appWidget); /** * This function is called when the RemoteViews of the app widget is updated * @param views The new RemoteViews to be set for the app widget * This function is called when the {@code RemoteViews} of the app widget is updated * @param views The new {@code RemoteViews} to be set for the app widget * * @hide */ void updateAppWidget(@Nullable RemoteViews views); /** * Called for the listener to handle deferred {@code RemoteViews} updates. Default * implementation is to update the widget directly. * @param packageName The package name used for uid verification on the service side * @param appWidgetId The widget id of the listener * * @hide */ default void updateAppWidgetDeferred(String packageName, int appWidgetId) { RemoteViews latestViews = null; try { latestViews = sService.getAppWidgetViews(packageName, appWidgetId); } catch (Exception e) { Log.e(TAG, "updateAppWidgetDeferred: ", e); } updateAppWidget(latestViews); } /** * This function is called when the view ID is changed for the app widget * @param viewId The new view ID to be be set for the widget Loading Loading @@ -563,6 +598,15 @@ public class AppWidgetHost { } } private void updateAppWidgetDeferred(int appWidgetId) { AppWidgetHostListener v = getListener(appWidgetId); if (v == null) { Log.e(TAG, "updateAppWidgetDeferred: null listener for id: " + appWidgetId); return; } v.updateAppWidgetDeferred(mContextOpPackageName, appWidgetId); } /** * Clear the list of Views that have been created by this AppWidgetHost. */ Loading core/java/android/widget/RemoteViews.java +13 −3 Original line number Diff line number Diff line Loading @@ -382,7 +382,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Maps Intent ID to RemoteCollectionItems to avoid duplicate items */ private RemoteCollectionCache mCollectionCache = new RemoteCollectionCache(); private @NonNull RemoteCollectionCache mCollectionCache = new RemoteCollectionCache(); /** Cache of ApplicationInfos used by collection items. */ private ApplicationInfoCache mApplicationInfoCache = new ApplicationInfoCache(); Loading Loading @@ -774,6 +774,16 @@ public class RemoteViews implements Parcelable, Filter { reconstructCaches(); } /** * Return {@code true} only if this {@code RemoteViews} is a legacy list widget that uses * {@code Intent} for inflating child entries. * * @hide */ public boolean isLegacyListRemoteViews() { return mCollectionCache.mIdToUriMapping.size() > 0; } /** * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission * grants will need to be issued to ensure the recipient of this object is able to render its Loading Loading @@ -1231,8 +1241,8 @@ public class RemoteViews implements Parcelable, Filter { } private class RemoteCollectionCache { private SparseArray<String> mIdToUriMapping = new SparseArray<>(); private HashMap<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>(); private final SparseArray<String> mIdToUriMapping = new SparseArray<>(); private final Map<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>(); RemoteCollectionCache() { } Loading core/java/com/android/internal/appwidget/IAppWidgetHost.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.widget.RemoteViews; /** {@hide} */ oneway interface IAppWidgetHost { void updateAppWidgetDeferred(int appWidgetId); void updateAppWidget(int appWidgetId, in RemoteViews views); void providerChanged(int appWidgetId, in AppWidgetProviderInfo info); void providersChanged(); Loading services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +33 −0 Original line number Diff line number Diff line Loading @@ -2292,11 +2292,32 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku args.arg4 = requestId; args.argi1 = widget.appWidgetId; if (updateViews.isLegacyListRemoteViews()) { mCallbackHandler.obtainMessage( CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED, args).sendToTarget(); return; } mCallbackHandler.obtainMessage( CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET, args).sendToTarget(); } private void handleNotifyUpdateAppWidgetDeferred(Host host, IAppWidgetHost callbacks, int appWidgetId, long requestId) { try { Slog.d(TAG, "Trying to notify widget update deferred for id: " + appWidgetId); callbacks.updateAppWidgetDeferred(appWidgetId); host.lastWidgetUpdateSequenceNo = requestId; } catch (RemoteException re) { synchronized (mLock) { Slog.e(TAG, "Widget host dead: " + host.id, re); host.callbacks = null; } } } private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks, int appWidgetId, RemoteViews views, long requestId) { try { Loading Loading @@ -4277,6 +4298,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3; public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4; public static final int MSG_NOTIFY_APP_WIDGET_REMOVED = 5; public static final int MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED = 6; public CallbackHandler(Looper looper) { super(looper, null, false); Loading Loading @@ -4340,6 +4362,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId, requestId); } break; case MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED: { SomeArgs args = (SomeArgs) message.obj; Host host = (Host) args.arg1; IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; long requestId = (Long) args.arg4; final int appWidgetId = args.argi1; args.recycle(); handleNotifyUpdateAppWidgetDeferred(host, callbacks, appWidgetId, requestId); } break; } } } Loading Loading
core/java/android/appwidget/AppWidgetHost.java +46 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; import android.widget.RemoteViews; import android.widget.RemoteViews.InteractionHandler; Loading @@ -52,12 +53,15 @@ import java.util.List; */ public class AppWidgetHost { private static final String TAG = "AppWidgetHost"; static final int HANDLE_UPDATE = 1; static final int HANDLE_PROVIDER_CHANGED = 2; static final int HANDLE_PROVIDERS_CHANGED = 3; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) static final int HANDLE_VIEW_DATA_CHANGED = 4; static final int HANDLE_APP_WIDGET_REMOVED = 5; static final int HANDLE_VIEW_UPDATE_DEFERRED = 6; final static Object sServiceLock = new Object(); @UnsupportedAppUsage Loading Loading @@ -131,6 +135,15 @@ public class AppWidgetHost { msg.sendToTarget(); } public void updateAppWidgetDeferred(int appWidgetId) { Handler handler = mWeakHandler.get(); if (handler == null) { return; } Message msg = handler.obtainMessage(HANDLE_VIEW_UPDATE_DEFERRED, appWidgetId, 0, null); msg.sendToTarget(); } private static boolean isLocalBinder() { return Process.myPid() == Binder.getCallingPid(); } Loading Loading @@ -163,6 +176,10 @@ public class AppWidgetHost { viewDataChanged(msg.arg1, msg.arg2); break; } case HANDLE_VIEW_UPDATE_DEFERRED: { updateAppWidgetDeferred(msg.arg1); break; } } } } Loading Loading @@ -480,13 +497,31 @@ public class AppWidgetHost { void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo appWidget); /** * This function is called when the RemoteViews of the app widget is updated * @param views The new RemoteViews to be set for the app widget * This function is called when the {@code RemoteViews} of the app widget is updated * @param views The new {@code RemoteViews} to be set for the app widget * * @hide */ void updateAppWidget(@Nullable RemoteViews views); /** * Called for the listener to handle deferred {@code RemoteViews} updates. Default * implementation is to update the widget directly. * @param packageName The package name used for uid verification on the service side * @param appWidgetId The widget id of the listener * * @hide */ default void updateAppWidgetDeferred(String packageName, int appWidgetId) { RemoteViews latestViews = null; try { latestViews = sService.getAppWidgetViews(packageName, appWidgetId); } catch (Exception e) { Log.e(TAG, "updateAppWidgetDeferred: ", e); } updateAppWidget(latestViews); } /** * This function is called when the view ID is changed for the app widget * @param viewId The new view ID to be be set for the widget Loading Loading @@ -563,6 +598,15 @@ public class AppWidgetHost { } } private void updateAppWidgetDeferred(int appWidgetId) { AppWidgetHostListener v = getListener(appWidgetId); if (v == null) { Log.e(TAG, "updateAppWidgetDeferred: null listener for id: " + appWidgetId); return; } v.updateAppWidgetDeferred(mContextOpPackageName, appWidgetId); } /** * Clear the list of Views that have been created by this AppWidgetHost. */ Loading
core/java/android/widget/RemoteViews.java +13 −3 Original line number Diff line number Diff line Loading @@ -382,7 +382,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Maps Intent ID to RemoteCollectionItems to avoid duplicate items */ private RemoteCollectionCache mCollectionCache = new RemoteCollectionCache(); private @NonNull RemoteCollectionCache mCollectionCache = new RemoteCollectionCache(); /** Cache of ApplicationInfos used by collection items. */ private ApplicationInfoCache mApplicationInfoCache = new ApplicationInfoCache(); Loading Loading @@ -774,6 +774,16 @@ public class RemoteViews implements Parcelable, Filter { reconstructCaches(); } /** * Return {@code true} only if this {@code RemoteViews} is a legacy list widget that uses * {@code Intent} for inflating child entries. * * @hide */ public boolean isLegacyListRemoteViews() { return mCollectionCache.mIdToUriMapping.size() > 0; } /** * Note all {@link Uri} that are referenced internally, with the expectation that Uri permission * grants will need to be issued to ensure the recipient of this object is able to render its Loading Loading @@ -1231,8 +1241,8 @@ public class RemoteViews implements Parcelable, Filter { } private class RemoteCollectionCache { private SparseArray<String> mIdToUriMapping = new SparseArray<>(); private HashMap<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>(); private final SparseArray<String> mIdToUriMapping = new SparseArray<>(); private final Map<String, RemoteCollectionItems> mUriToCollectionMapping = new HashMap<>(); RemoteCollectionCache() { } Loading
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.widget.RemoteViews; /** {@hide} */ oneway interface IAppWidgetHost { void updateAppWidgetDeferred(int appWidgetId); void updateAppWidget(int appWidgetId, in RemoteViews views); void providerChanged(int appWidgetId, in AppWidgetProviderInfo info); void providersChanged(); Loading
services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +33 −0 Original line number Diff line number Diff line Loading @@ -2292,11 +2292,32 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku args.arg4 = requestId; args.argi1 = widget.appWidgetId; if (updateViews.isLegacyListRemoteViews()) { mCallbackHandler.obtainMessage( CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED, args).sendToTarget(); return; } mCallbackHandler.obtainMessage( CallbackHandler.MSG_NOTIFY_UPDATE_APP_WIDGET, args).sendToTarget(); } private void handleNotifyUpdateAppWidgetDeferred(Host host, IAppWidgetHost callbacks, int appWidgetId, long requestId) { try { Slog.d(TAG, "Trying to notify widget update deferred for id: " + appWidgetId); callbacks.updateAppWidgetDeferred(appWidgetId); host.lastWidgetUpdateSequenceNo = requestId; } catch (RemoteException re) { synchronized (mLock) { Slog.e(TAG, "Widget host dead: " + host.id, re); host.callbacks = null; } } } private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks, int appWidgetId, RemoteViews views, long requestId) { try { Loading Loading @@ -4277,6 +4298,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku public static final int MSG_NOTIFY_PROVIDERS_CHANGED = 3; public static final int MSG_NOTIFY_VIEW_DATA_CHANGED = 4; public static final int MSG_NOTIFY_APP_WIDGET_REMOVED = 5; public static final int MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED = 6; public CallbackHandler(Looper looper) { super(looper, null, false); Loading Loading @@ -4340,6 +4362,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku handleNotifyAppWidgetViewDataChanged(host, callbacks, appWidgetId, viewId, requestId); } break; case MSG_NOTIFY_UPDATE_APP_WIDGET_DEFERRED: { SomeArgs args = (SomeArgs) message.obj; Host host = (Host) args.arg1; IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2; long requestId = (Long) args.arg4; final int appWidgetId = args.argi1; args.recycle(); handleNotifyUpdateAppWidgetDeferred(host, callbacks, appWidgetId, requestId); } break; } } } Loading