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

Commit e7e56310 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Avoding writing ApplicationInfo multiple times for nested RemoteViews"

parents 668868ba 5d8bcdf6
Loading
Loading
Loading
Loading
+36 −13
Original line number Diff line number Diff line
@@ -324,6 +324,14 @@ public class RemoteViews implements Parcelable, Filter {
            return false;
        }

        /**
         * Overridden by subclasses which have (or inherit) an ApplicationInfo instance
         * as member variable
         */
        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
            return true;
        }

        int viewId;
    }

@@ -1521,11 +1529,11 @@ public class RemoteViews implements Parcelable, Filter {
            }
        }

        public ViewGroupAction(Parcel parcel, BitmapCache bitmapCache) {
        ViewGroupAction(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
            viewId = parcel.readInt();
            boolean nestedViewsNull = parcel.readInt() == 0;
            if (!nestedViewsNull) {
                nestedViews = new RemoteViews(parcel, bitmapCache);
                nestedViews = new RemoteViews(parcel, bitmapCache, info);
            } else {
                nestedViews = null;
            }
@@ -1543,6 +1551,13 @@ public class RemoteViews implements Parcelable, Filter {
            }
        }

        @Override
        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
            return nestedViews != null
                    && nestedViews.mApplication.packageName.equals(parentInfo.packageName)
                    && nestedViews.mApplication.uid == parentInfo.uid;
        }

        @Override
        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
            final Context context = root.getContext();
@@ -2195,10 +2210,10 @@ public class RemoteViews implements Parcelable, Filter {
     * @param parcel
     */
    public RemoteViews(Parcel parcel) {
        this(parcel, null);
        this(parcel, null, null);
    }

    private RemoteViews(Parcel parcel, BitmapCache bitmapCache) {
    private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
        int mode = parcel.readInt();

        // We only store a bitmap cache in the root of the RemoteViews.
@@ -2210,7 +2225,8 @@ public class RemoteViews implements Parcelable, Filter {
        }

        if (mode == MODE_NORMAL) {
            mApplication = parcel.readParcelable(null);
            mApplication = parcel.readInt() == 0 ? info :
                    ApplicationInfo.CREATOR.createFromParcel(parcel);
            mLayoutId = parcel.readInt();
            mIsWidgetCollectionChild = parcel.readInt() == 1;

@@ -2230,7 +2246,7 @@ public class RemoteViews implements Parcelable, Filter {
                            mActions.add(new ReflectionAction(parcel));
                            break;
                        case ViewGroupAction.TAG:
                            mActions.add(new ViewGroupAction(parcel, mBitmapCache));
                            mActions.add(new ViewGroupAction(parcel, mBitmapCache, mApplication));
                            break;
                        case ReflectionActionWithoutParams.TAG:
                            mActions.add(new ReflectionActionWithoutParams(parcel));
@@ -2278,8 +2294,8 @@ public class RemoteViews implements Parcelable, Filter {
            }
        } else {
            // MODE_HAS_LANDSCAPE_AND_PORTRAIT
            mLandscape = new RemoteViews(parcel, mBitmapCache);
            mPortrait = new RemoteViews(parcel, mBitmapCache);
            mLandscape = new RemoteViews(parcel, mBitmapCache, info);
            mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication);
            mApplication = mPortrait.mApplication;
            mLayoutId = mPortrait.getLayoutId();
        }
@@ -2299,11 +2315,11 @@ public class RemoteViews implements Parcelable, Filter {
        // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
        // Instead pretend we're not owning the cache while parceling.
        mIsRoot = false;
        writeToParcel(p, 0);
        writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
        p.setDataPosition(0);
        mIsRoot = true;

        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone());
        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication);
        rv.mIsRoot = true;

        p.recycle();
@@ -3536,7 +3552,12 @@ public class RemoteViews implements Parcelable, Filter {
            if (mIsRoot) {
                mBitmapCache.writeBitmapsToParcel(dest, flags);
            }
            dest.writeParcelable(mApplication, flags);
            if (!mIsRoot && (flags & PARCELABLE_ELIDE_DUPLICATES) != 0) {
                dest.writeInt(0);
            } else {
                dest.writeInt(1);
                mApplication.writeToParcel(dest, flags);
            }
            dest.writeInt(mLayoutId);
            dest.writeInt(mIsWidgetCollectionChild ? 1 : 0);
            int count;
@@ -3548,7 +3569,8 @@ public class RemoteViews implements Parcelable, Filter {
            dest.writeInt(count);
            for (int i=0; i<count; i++) {
                Action a = mActions.get(i);
                a.writeToParcel(dest, 0);
                a.writeToParcel(dest, a.hasSameAppInfo(mApplication)
                        ? PARCELABLE_ELIDE_DUPLICATES : 0);
            }
        } else {
            dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT);
@@ -3558,7 +3580,8 @@ public class RemoteViews implements Parcelable, Filter {
                mBitmapCache.writeBitmapsToParcel(dest, flags);
            }
            mLandscape.writeToParcel(dest, flags);
            mPortrait.writeToParcel(dest, flags);
            // Both RemoteViews already share the same package and user
            mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES);
        }
    }

+45 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -35,6 +36,7 @@ import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

/**
 * Tests for RemoteViews.
@@ -43,6 +45,9 @@ import static org.junit.Assert.assertSame;
@SmallTest
public class RemoteViewsTest {

    // This can point to any other package which exists on the device.
    private static final String OTHER_PACKAGE = "com.android.systemui";

    @Rule
    public final ExpectedException exception = ExpectedException.none();

@@ -121,4 +126,44 @@ public class RemoteViewsTest {
        clone.apply(mContext, mContainer);
    }

    @Test
    public void parcelSize_nestedViews() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
        // We don't care about the actual layout id.
        RemoteViews child = new RemoteViews(mPackage, 33);
        int expectedSize = getParcelSize(original) + getParcelSize(child);
        original.addView(R.id.layout, child);

        // The application info will get written only once.
        assertTrue(getParcelSize(original) < expectedSize);
        assertEquals(getParcelSize(original), getParcelSize(original.clone()));

        original = new RemoteViews(mPackage, R.layout.remote_views_test);
        child = new RemoteViews(OTHER_PACKAGE, 33);
        expectedSize = getParcelSize(original) + getParcelSize(child);
        original.addView(R.id.layout, child);

        // Both the views will get written completely along with an additional view operation
        assertTrue(getParcelSize(original) > expectedSize);
        assertEquals(getParcelSize(original), getParcelSize(original.clone()));
    }

    @Test
    public void parcelSize_differentOrientation() {
        RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test);
        RemoteViews portrait = new RemoteViews(mPackage, 33);

        // The application info will get written only once.
        RemoteViews views = new RemoteViews(landscape, portrait);
        assertTrue(getParcelSize(views) < (getParcelSize(landscape) + getParcelSize(portrait)));
        assertEquals(getParcelSize(views), getParcelSize(views.clone()));
    }

    private int getParcelSize(RemoteViews view) {
        Parcel parcel = Parcel.obtain();
        view.writeToParcel(parcel, 0);
        int size = parcel.dataSize();
        parcel.recycle();
        return size;
    }
}