diff options
-rw-r--r-- | services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 569615e1683c..f9b731db75b1 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -217,6 +217,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku // See {@link Provider#pendingDeletedWidgetIds}. private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids"; + // Hard limit of number of hosts an app can create, note that the app that hosts the widgets + // can have multiple instances of {@link AppWidgetHost}, typically in respect to different + // surfaces in the host app. + // @see AppWidgetHost + // @see AppWidgetHost#mHostId + private static final int MAX_NUMBER_OF_HOSTS_PER_PACKAGE = 20; + // Hard limit of number of widgets can be pinned by a host. + private static final int MAX_NUMBER_OF_WIDGETS_PER_HOST = 200; + // Handles user and package related broadcasts. // See {@link #registerBroadcastReceiver} private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -2275,7 +2284,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (host != null) { return host; } - + ensureHostCountBeforeAddLocked(id); host = new Host(); host.id = id; mHosts.add(host); @@ -2283,6 +2292,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku return host; } + /** + * Ensures that the number of hosts for a package is less than the maximum number of hosts per + * package. If the number of hosts is greater than the maximum number of hosts per package, then + * removes the oldest host. + */ + private void ensureHostCountBeforeAddLocked(@NonNull final HostId hostId) { + final List<Host> hosts = new ArrayList<>(); + for (Host host : mHosts) { + if (host.id.uid == hostId.uid + && host.id.packageName.equals(hostId.packageName)) { + hosts.add(host); + } + } + while (hosts.size() >= MAX_NUMBER_OF_HOSTS_PER_PACKAGE) { + deleteHostLocked(hosts.remove(0)); + } + } + private void deleteHostLocked(Host host) { if (DEBUG) { Slog.i(TAG, "deleteHostLocked() " + host); @@ -3573,12 +3600,33 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (DEBUG) { Slog.i(TAG, "addWidgetLocked() " + widget); } + ensureWidgetCountBeforeAddLocked(widget); mWidgets.add(widget); onWidgetProviderAddedOrChangedLocked(widget); } /** + * Ensures that the widget count for the widget's host is not greater than the maximum + * number of widgets per host. If the count is greater than the maximum, removes oldest widgets + * from the host until the count is less than or equal to the maximum. + */ + private void ensureWidgetCountBeforeAddLocked(@NonNull final Widget widget) { + if (widget.host == null || widget.host.id == null) { + return; + } + final List<Widget> widgetsInSameHost = new ArrayList<>(); + for (Widget w : mWidgets) { + if (w.host != null && widget.host.id.equals(w.host.id)) { + widgetsInSameHost.add(w); + } + } + while (widgetsInSameHost.size() >= MAX_NUMBER_OF_WIDGETS_PER_HOST) { + removeWidgetLocked(widgetsInSameHost.remove(0)); + } + } + + /** * Checks if the provider is assigned and updates the mWidgetPackages to track packages * that have bound widgets. */ |