Loading core/java/android/appwidget/AppWidgetManager.java +108 −19 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UiThread; import android.annotation.UserIdInt; import android.app.IServiceConnection; import android.app.PendingIntent; Loading @@ -39,6 +40,10 @@ import android.content.pm.ShortcutInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.util.DisplayMetrics; Loading @@ -53,6 +58,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; /** * Updates AppWidget state; gets information about installed AppWidget providers and other Loading Loading @@ -475,6 +481,8 @@ public class AppWidgetManager { private static final String TAG = "AppWidgetManager"; private static Executor sUpdateExecutor; /** * An intent extra that contains multiple appWidgetIds. These are id values as * they were provided to the application during a recent restore from backup. It is Loading Loading @@ -510,6 +518,8 @@ public class AppWidgetManager { private final IAppWidgetService mService; private final DisplayMetrics mDisplayMetrics; private boolean mHasPostedLegacyLists = false; /** * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context * Context} object. Loading Loading @@ -552,6 +562,13 @@ public class AppWidgetManager { }); } private boolean isPostingTaskToBackground(@Nullable RemoteViews views) { return Looper.myLooper() == Looper.getMainLooper() && RemoteViews.isAdapterConversionEnabled() && (mHasPostedLegacyLists = mHasPostedLegacyLists || (views != null && views.hasLegacyLists())); } /** * Set the RemoteViews to use for the specified appWidgetIds. * <p> Loading @@ -575,6 +592,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.updateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Log.e(TAG, "Error updating app widget views in background", e); } }); return; } try { mService.updateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Loading Loading @@ -683,6 +713,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Log.e(TAG, "Error partially updating app widget views in background", e); } }); return; } try { mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Loading Loading @@ -738,6 +781,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.updateAppWidgetProvider(provider, views); } catch (RemoteException e) { Log.e(TAG, "Error updating app widget view using provider in background", e); } }); return; } try { mService.updateAppWidgetProvider(provider, views); } catch (RemoteException e) { Loading Loading @@ -786,8 +842,28 @@ public class AppWidgetManager { if (mService == null) { return; } if (!RemoteViews.isAdapterConversionEnabled()) { try { mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } return; } if (Looper.myLooper() == Looper.getMainLooper()) { mHasPostedLegacyLists = true; createUpdateExecutorIfNull().execute(() -> notifyCollectionWidgetChange(appWidgetIds, viewId)); } else { notifyCollectionWidgetChange(appWidgetIds, viewId); } } private void notifyCollectionWidgetChange(int[] appWidgetIds, int viewId) { try { if (RemoteViews.isAdapterConversionEnabled()) { List<CompletableFuture<Void>> updateFutures = new ArrayList<>(); for (int i = 0; i < appWidgetIds.length; i++) { final int widgetId = appWidgetIds[i]; Loading @@ -803,11 +879,8 @@ public class AppWidgetManager { })); } CompletableFuture.allOf(updateFutures.toArray(CompletableFuture[]::new)).join(); } else { mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (Exception e) { Log.e(TAG, "Error notifying changes for all widgets", e); } } Loading Loading @@ -1338,4 +1411,20 @@ public class AppWidgetManager { throw e.rethrowFromSystemServer(); } } @UiThread private static @NonNull Executor createUpdateExecutorIfNull() { if (sUpdateExecutor == null) { sUpdateExecutor = new HandlerExecutor(createAndStartNewHandler( "widget_manager_update_helper_thread", Process.THREAD_PRIORITY_FOREGROUND)); } return sUpdateExecutor; } private static @NonNull Handler createAndStartNewHandler(@NonNull String name, int priority) { HandlerThread thread = new HandlerThread(name, priority); thread.start(); return thread.getThreadHandler(); } } core/java/android/widget/RemoteViews.java +41 −0 Original line number Diff line number Diff line Loading @@ -801,6 +801,11 @@ public class RemoteViews implements Parcelable, Filter { mActions.set(i, new SetRemoteCollectionItemListAdapterAction(itemsAction.viewId, itemsAction.mServiceIntent)); isActionReplaced = true; } else if (action instanceof SetRemoteViewsAdapterIntent intentAction && intentAction.viewId == viewId) { mActions.set(i, new SetRemoteCollectionItemListAdapterAction( intentAction.viewId, intentAction.intent)); isActionReplaced = true; } else if (action instanceof ViewGroupActionAdd groupAction && groupAction.mNestedViews != null) { isActionReplaced |= groupAction.mNestedViews.replaceRemoteCollections(viewId); Loading @@ -822,6 +827,42 @@ public class RemoteViews implements Parcelable, Filter { return isActionReplaced; } /** * @return True if has set remote adapter using service intent * @hide */ public boolean hasLegacyLists() { if (mActions != null) { for (int i = 0; i < mActions.size(); i++) { Action action = mActions.get(i); if ((action instanceof SetRemoteCollectionItemListAdapterAction itemsAction && itemsAction.mServiceIntent != null) || (action instanceof SetRemoteViewsAdapterIntent intentAction && intentAction.intent != null) || (action instanceof ViewGroupActionAdd groupAction && groupAction.mNestedViews != null && groupAction.mNestedViews.hasLegacyLists())) { return true; } } } if (mSizedRemoteViews != null) { for (int i = 0; i < mSizedRemoteViews.size(); i++) { if (mSizedRemoteViews.get(i).hasLegacyLists()) { return true; } } } if (mLandscape != null && mLandscape.hasLegacyLists()) { return true; } if (mPortrait != null && mPortrait.hasLegacyLists()) { return true; } return false; } private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) { if (icon != null && (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { Loading Loading
core/java/android/appwidget/AppWidgetManager.java +108 −19 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UiThread; import android.annotation.UserIdInt; import android.app.IServiceConnection; import android.app.PendingIntent; Loading @@ -39,6 +40,10 @@ import android.content.pm.ShortcutInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.util.DisplayMetrics; Loading @@ -53,6 +58,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; /** * Updates AppWidget state; gets information about installed AppWidget providers and other Loading Loading @@ -475,6 +481,8 @@ public class AppWidgetManager { private static final String TAG = "AppWidgetManager"; private static Executor sUpdateExecutor; /** * An intent extra that contains multiple appWidgetIds. These are id values as * they were provided to the application during a recent restore from backup. It is Loading Loading @@ -510,6 +518,8 @@ public class AppWidgetManager { private final IAppWidgetService mService; private final DisplayMetrics mDisplayMetrics; private boolean mHasPostedLegacyLists = false; /** * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context * Context} object. Loading Loading @@ -552,6 +562,13 @@ public class AppWidgetManager { }); } private boolean isPostingTaskToBackground(@Nullable RemoteViews views) { return Looper.myLooper() == Looper.getMainLooper() && RemoteViews.isAdapterConversionEnabled() && (mHasPostedLegacyLists = mHasPostedLegacyLists || (views != null && views.hasLegacyLists())); } /** * Set the RemoteViews to use for the specified appWidgetIds. * <p> Loading @@ -575,6 +592,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.updateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Log.e(TAG, "Error updating app widget views in background", e); } }); return; } try { mService.updateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Loading Loading @@ -683,6 +713,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Log.e(TAG, "Error partially updating app widget views in background", e); } }); return; } try { mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views); } catch (RemoteException e) { Loading Loading @@ -738,6 +781,19 @@ public class AppWidgetManager { if (mService == null) { return; } if (isPostingTaskToBackground(views)) { createUpdateExecutorIfNull().execute(() -> { try { mService.updateAppWidgetProvider(provider, views); } catch (RemoteException e) { Log.e(TAG, "Error updating app widget view using provider in background", e); } }); return; } try { mService.updateAppWidgetProvider(provider, views); } catch (RemoteException e) { Loading Loading @@ -786,8 +842,28 @@ public class AppWidgetManager { if (mService == null) { return; } if (!RemoteViews.isAdapterConversionEnabled()) { try { mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } return; } if (Looper.myLooper() == Looper.getMainLooper()) { mHasPostedLegacyLists = true; createUpdateExecutorIfNull().execute(() -> notifyCollectionWidgetChange(appWidgetIds, viewId)); } else { notifyCollectionWidgetChange(appWidgetIds, viewId); } } private void notifyCollectionWidgetChange(int[] appWidgetIds, int viewId) { try { if (RemoteViews.isAdapterConversionEnabled()) { List<CompletableFuture<Void>> updateFutures = new ArrayList<>(); for (int i = 0; i < appWidgetIds.length; i++) { final int widgetId = appWidgetIds[i]; Loading @@ -803,11 +879,8 @@ public class AppWidgetManager { })); } CompletableFuture.allOf(updateFutures.toArray(CompletableFuture[]::new)).join(); } else { mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (Exception e) { Log.e(TAG, "Error notifying changes for all widgets", e); } } Loading Loading @@ -1338,4 +1411,20 @@ public class AppWidgetManager { throw e.rethrowFromSystemServer(); } } @UiThread private static @NonNull Executor createUpdateExecutorIfNull() { if (sUpdateExecutor == null) { sUpdateExecutor = new HandlerExecutor(createAndStartNewHandler( "widget_manager_update_helper_thread", Process.THREAD_PRIORITY_FOREGROUND)); } return sUpdateExecutor; } private static @NonNull Handler createAndStartNewHandler(@NonNull String name, int priority) { HandlerThread thread = new HandlerThread(name, priority); thread.start(); return thread.getThreadHandler(); } }
core/java/android/widget/RemoteViews.java +41 −0 Original line number Diff line number Diff line Loading @@ -801,6 +801,11 @@ public class RemoteViews implements Parcelable, Filter { mActions.set(i, new SetRemoteCollectionItemListAdapterAction(itemsAction.viewId, itemsAction.mServiceIntent)); isActionReplaced = true; } else if (action instanceof SetRemoteViewsAdapterIntent intentAction && intentAction.viewId == viewId) { mActions.set(i, new SetRemoteCollectionItemListAdapterAction( intentAction.viewId, intentAction.intent)); isActionReplaced = true; } else if (action instanceof ViewGroupActionAdd groupAction && groupAction.mNestedViews != null) { isActionReplaced |= groupAction.mNestedViews.replaceRemoteCollections(viewId); Loading @@ -822,6 +827,42 @@ public class RemoteViews implements Parcelable, Filter { return isActionReplaced; } /** * @return True if has set remote adapter using service intent * @hide */ public boolean hasLegacyLists() { if (mActions != null) { for (int i = 0; i < mActions.size(); i++) { Action action = mActions.get(i); if ((action instanceof SetRemoteCollectionItemListAdapterAction itemsAction && itemsAction.mServiceIntent != null) || (action instanceof SetRemoteViewsAdapterIntent intentAction && intentAction.intent != null) || (action instanceof ViewGroupActionAdd groupAction && groupAction.mNestedViews != null && groupAction.mNestedViews.hasLegacyLists())) { return true; } } } if (mSizedRemoteViews != null) { for (int i = 0; i < mSizedRemoteViews.size(); i++) { if (mSizedRemoteViews.get(i).hasLegacyLists()) { return true; } } } if (mLandscape != null && mLandscape.hasLegacyLists()) { return true; } if (mPortrait != null && mPortrait.hasLegacyLists()) { return true; } return false; } private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) { if (icon != null && (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { Loading