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

Commit 36af1e4c authored by Sihua Ma's avatar Sihua Ma
Browse files

Move getRemoteCollectionItems to RemoteViewsFactory

This brings more accuracy when estimating the collection size as Bitmap
in the local service could share the same address, so the BitmapCache
could contain fewer duplicates. Additionally the ApplicationInfo will be
having the same address which allows us to utilize allowSquashing to
eliminate duplicate writes to the parcel

Manually verified that the size of the collection shrinks by ~33% from
600k to 400k

Test: Manual
Bug: 245950570
Change-Id: I16ddba00465e64613f6dbe836da6bd0693da7d4c
parent dc95e818
Loading
Loading
Loading
Loading
+36 −23
Original line number Diff line number Diff line
@@ -124,6 +124,41 @@ public abstract class RemoteViewsService extends Service {
         * @return True if the same id always refers to the same object.
         */
        public boolean hasStableIds();

        /**
         * @hide
         */
        default RemoteViews.RemoteCollectionItems getRemoteCollectionItems(int capSize) {
            RemoteViews.RemoteCollectionItems items = new RemoteViews.RemoteCollectionItems
                    .Builder().build();
            Parcel capSizeTestParcel = Parcel.obtain();
            capSizeTestParcel.allowSquashing();

            try {
                RemoteViews.RemoteCollectionItems.Builder itemsBuilder =
                        new RemoteViews.RemoteCollectionItems.Builder();
                onDataSetChanged();

                itemsBuilder.setHasStableIds(hasStableIds());
                final int numOfEntries = getCount();

                for (int i = 0; i < numOfEntries; i++) {
                    final long currentItemId = getItemId(i);
                    final RemoteViews currentView = getViewAt(i);
                    currentView.writeToParcel(capSizeTestParcel, 0);
                    if (capSizeTestParcel.dataSize() > capSize) {
                        break;
                    }
                    itemsBuilder.addItem(currentItemId, currentView);
                }

                items = itemsBuilder.build();
            } finally {
                // Recycle the parcel
                capSizeTestParcel.recycle();
            }
            return items;
        }
    }

    /**
@@ -232,33 +267,11 @@ public abstract class RemoteViewsService extends Service {
        public RemoteViews.RemoteCollectionItems getRemoteCollectionItems(int capSize) {
            RemoteViews.RemoteCollectionItems items = new RemoteViews.RemoteCollectionItems
                    .Builder().build();
            Parcel capSizeTestParcel = Parcel.obtain();

            try {
                RemoteViews.RemoteCollectionItems.Builder itemsBuilder =
                        new RemoteViews.RemoteCollectionItems.Builder();
                mFactory.onDataSetChanged();

                itemsBuilder.setHasStableIds(mFactory.hasStableIds());
                final int numOfEntries = mFactory.getCount();

                for (int i = 0; i < numOfEntries; i++) {
                    final long currentItemId = mFactory.getItemId(i);
                    final RemoteViews currentView = mFactory.getViewAt(i);
                    currentView.writeToParcel(capSizeTestParcel, 0);
                    if (capSizeTestParcel.dataSize() > capSize) {
                        break;
                    }
                    itemsBuilder.addItem(currentItemId, currentView);
                }

                items = itemsBuilder.build();
                items = mFactory.getRemoteCollectionItems(capSize);
            } catch (Exception ex) {
                Thread t = Thread.currentThread();
                Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, ex);
            } finally {
                // Recycle the parcel
                capSizeTestParcel.recycle();
            }
            return items;
        }