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

Commit 6f54b224 authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Don't copy Bitmaps when cloning RemoteViews" into nyc-dev

parents e00ffb51 7da889d8
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.widget.AdapterView.OnItemClickListener;
import libcore.util.Objects;

import com.android.internal.R;
import com.android.internal.util.Preconditions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -1096,6 +1097,13 @@ public class RemoteViews implements Parcelable, Filter {
                memoryCounter.addBitmapMemory(mBitmaps.get(i));
            }
        }

        @Override
        protected BitmapCache clone() {
            BitmapCache bitmapCache = new BitmapCache();
            bitmapCache.mBitmaps.addAll(mBitmaps);
            return bitmapCache;
        }
    }

    private class BitmapReflectionAction extends Action {
@@ -2227,10 +2235,21 @@ public class RemoteViews implements Parcelable, Filter {


    public RemoteViews clone() {
        Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
                + "May only clone the root of a RemoteView hierarchy.");

        Parcel p = Parcel.obtain();

        // 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);
        p.setDataPosition(0);
        RemoteViews rv = new RemoteViews(p);
        mIsRoot = true;

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

        p.recycle();
        return rv;
    }
@@ -2240,7 +2259,7 @@ public class RemoteViews implements Parcelable, Filter {
    }

    /**
     * Reutrns the layout id of the root layout associated with this RemoteViews. In the case
     * Returns the layout id of the root layout associated with this RemoteViews. In the case
     * that the RemoteViews has both a landscape and portrait root, this will return the layout
     * id associated with the portrait layout.
     *
+32 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2016 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/layout"
        android:orientation="vertical">

    <TextView android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <ImageView android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

</LinearLayout>
+127 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.view;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;

import com.android.frameworks.coretests.R;

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

/**
 * Tests for RemoteViews.
 */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class RemoteViewsTest {

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

    private Context mContext;
    private String mPackage;
    private LinearLayout mContainer;

    @Before
    public void setup() {
        mContext = InstrumentationRegistry.getContext();
        mPackage = mPackage;
        mContainer = new LinearLayout(mContext);
    }

    @Test
    public void clone_doesNotCopyBitmap() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
        Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);

        original.setImageViewBitmap(R.id.image, bitmap);
        RemoteViews clone = original.clone();
        View inflated = clone.apply(mContext, mContainer);

        Drawable drawable = ((ImageView) inflated.findViewById(R.id.image)).getDrawable();
        assertSame(bitmap, ((BitmapDrawable)drawable).getBitmap());
    }

    @Test
    public void clone_originalCanStillBeApplied() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);

        RemoteViews clone = original.clone();

        clone.apply(mContext, mContainer);
    }

    @Test
    public void clone_clones() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);

        RemoteViews clone = original.clone();
        original.setTextViewText(R.id.text, "test");
        View inflated = clone.apply(mContext, mContainer);

        TextView textView = (TextView) inflated.findViewById(R.id.text);
        assertEquals("", textView.getText());
    }

    @Test
    public void clone_child_fails() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
        RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_test);

        original.addView(R.id.layout, child);

        exception.expect(IllegalStateException.class);
        RemoteViews clone = child.clone();
    }

    @Test
    public void clone_repeatedly() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);

        original.clone();
        original.clone();

        original.apply(mContext, mContainer);
    }

    @Test
    public void clone_chained() {
        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);

        RemoteViews clone = original.clone().clone();

        clone.apply(mContext, mContainer);
    }

}