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

Commit 404b2e3f authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8783759 from 7e0149d2 to tm-qpr1-release

Change-Id: I0e455f7c433fc5af5b15426237f9501bf4537db0
parents 5f299266 7e0149d2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -54,6 +54,12 @@ public abstract class AdbManagerInternal {
     */
    public abstract File getAdbTempKeysFile();

    /**
     * Notify the AdbManager that the key files have changed and any in-memory state should be
     * reloaded.
     */
    public abstract void notifyKeyFilesUpdated();

    /**
     * Starts adbd for a transport.
     */
+12 −0
Original line number Diff line number Diff line
@@ -57,6 +57,18 @@
        { "include-filter": "com.android.server.am.BatteryExternalStatsWorkerTest" }
      ]
    },
    {
      "file_patterns": [
        "Parcel\\.java",
        "[^/]*Bundle[^/]*\\.java"
      ],
      "name": "FrameworksMockingCoreTests",
      "options": [
        { "include-filter":  "android.os.BundleRecyclingTest"},
        { "exclude-annotation": "androidx.test.filters.FlakyTest" },
        { "exclude-annotation": "org.junit.Ignore" }
      ]
    },
    {
      "file_patterns": [
        "BatteryUsageStats[^/]*\\.java",
+256 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.os;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;

import android.platform.test.annotations.Presubmit;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.dx.mockito.inline.extended.StaticMockitoSession;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Test for verifying {@link android.os.Bundle} recycles the underlying parcel where needed.
 *
 * <p>Build/Install/Run:
 *  atest FrameworksMockingCoreTests:android.os.BundleRecyclingTest
 */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class BundleRecyclingTest {
    private Parcel mParcelSpy;
    private Bundle mBundle;

    @Before
    public void setUp() throws Exception {
        setUpBundle(/* hasLazy */ true);
    }

    @Test
    public void bundleClear_whenUnparcelledWithoutLazy_recyclesParcelOnce() {
        setUpBundle(/* hasLazy */ false);
        // Will unparcel and immediately recycle parcel
        assertNotNull(mBundle.getString("key"));
        verify(mParcelSpy, times(1)).recycle();
        assertFalse(mBundle.isDefinitelyEmpty());

        // Should not recycle again
        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
        assertTrue(mBundle.isDefinitelyEmpty());
    }

    @Test
    public void bundleClear_whenParcelled_recyclesParcel() {
        assertTrue(mBundle.isParcelled());
        verify(mParcelSpy, times(0)).recycle();

        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
        assertTrue(mBundle.isDefinitelyEmpty());

        // Should not recycle again
        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
    }

    @Test
    public void bundleClear_whenUnparcelledWithLazyValueUnwrapped_recyclesParcel() {
        // Will unparcel with a lazy value, and immediately unwrap the lazy value,
        // with no lazy values left at the end of getParcelable
        assertNotNull(mBundle.getParcelable("key", CustomParcelable.class));
        verify(mParcelSpy, times(0)).recycle();

        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
        assertTrue(mBundle.isDefinitelyEmpty());

        // Should not recycle again
        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
    }

    @Test
    public void bundleClear_whenUnparcelledWithLazy_recyclesParcel() {
        // Will unparcel but keep the CustomParcelable lazy
        assertFalse(mBundle.isEmpty());
        verify(mParcelSpy, times(0)).recycle();

        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
        assertTrue(mBundle.isDefinitelyEmpty());

        // Should not recycle again
        mBundle.clear();
        verify(mParcelSpy, times(1)).recycle();
    }

    @Test
    public void bundleClear_whenClearedWithSharedParcel_doesNotRecycleParcel() {
        Bundle copy = new Bundle();
        copy.putAll(mBundle);

        mBundle.clear();
        assertTrue(mBundle.isDefinitelyEmpty());

        copy.clear();
        assertTrue(copy.isDefinitelyEmpty());

        verify(mParcelSpy, never()).recycle();
    }

    @Test
    public void bundleClear_whenClearedWithCopiedParcel_doesNotRecycleParcel() {
        // Will unparcel but keep the CustomParcelable lazy
        assertFalse(mBundle.isEmpty());

        Bundle copy = mBundle.deepCopy();
        copy.putAll(mBundle);

        mBundle.clear();
        assertTrue(mBundle.isDefinitelyEmpty());

        copy.clear();
        assertTrue(copy.isDefinitelyEmpty());

        verify(mParcelSpy, never()).recycle();
    }

    private void setUpBundle(boolean hasLazy) {
        AtomicReference<Parcel> parcel = new AtomicReference<>();
        StaticMockitoSession session = mockitoSession()
                .strictness(Strictness.STRICT_STUBS)
                .spyStatic(Parcel.class)
                .startMocking();
        doAnswer((Answer<Parcel>) invocationOnSpy -> {
            Parcel spy = (Parcel) invocationOnSpy.callRealMethod();
            spyOn(spy);
            parcel.set(spy);
            return spy;
        }).when(() -> Parcel.obtain());

        Bundle bundle = new Bundle();
        bundle.setClassLoader(getClass().getClassLoader());
        Parcel p = createBundle(hasLazy);
        bundle.readFromParcel(p);
        p.recycle();

        session.finishMocking();

        mParcelSpy = parcel.get();
        mBundle = bundle;
    }

    /**
     * Create a test bundle, parcel it and return the parcel.
     */
    private Parcel createBundle(boolean hasLazy) {
        final Bundle source = new Bundle();
        if (hasLazy) {
            source.putParcelable("key", new CustomParcelable(13, "Tiramisu"));
        } else {
            source.putString("key", "tiramisu");
        }
        return getParcelledBundle(source);
    }

    /**
     * Take a bundle, write it to a parcel and return the parcel.
     */
    private Parcel getParcelledBundle(Bundle bundle) {
        final Parcel p = Parcel.obtain();
        // Don't use p.writeParcelabe(), which would write the creator, which we don't need.
        bundle.writeToParcel(p, 0);
        p.setDataPosition(0);
        return p;
    }

    private static class CustomParcelable implements Parcelable {
        public final int integer;
        public final String string;

        CustomParcelable(int integer, String string) {
            this.integer = integer;
            this.string = string;
        }

        protected CustomParcelable(Parcel in) {
            integer = in.readInt();
            string = in.readString();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            out.writeInt(integer);
            out.writeString(string);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) {
                return true;
            }
            if (!(other instanceof CustomParcelable)) {
                return false;
            }
            CustomParcelable that = (CustomParcelable) other;
            return integer == that.integer && string.equals(that.string);
        }

        @Override
        public int hashCode() {
            return Objects.hash(integer, string);
        }

        public static final Creator<CustomParcelable> CREATOR = new Creator<CustomParcelable>() {
            @Override
            public CustomParcelable createFromParcel(Parcel in) {
                return new CustomParcelable(in);
            }
            @Override
            public CustomParcelable[] newArray(int size) {
                return new CustomParcelable[size];
            }
        };
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -51,6 +51,17 @@
        }
      ]
    },
    {
      "name": "SystemUIGoogleScreenshotTests",
      "options": [
        {
          "exclude-annotation": "org.junit.Ignore"
        },
        {
          "exclude-annotation": "androidx.test.filters.FlakyTest"
        }
      ]
    },
    {
      // Permission indicators
      "name": "CtsPermission4TestCases",
+2 −3
Original line number Diff line number Diff line
@@ -14,20 +14,19 @@
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<!-- TODO(b/203800646): layout_marginTop doesn't seem to work on some large screens. -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/media_ttt_receiver_chip"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/media_ttt_chip_background_receiver"
    >

    <com.android.internal.widget.CachingIconView
        android:id="@+id/app_icon"
        android:layout_width="@dimen/media_ttt_icon_size_receiver"
        android:layout_height="@dimen/media_ttt_icon_size_receiver"
        android:layout_gravity="center"
        android:layout_gravity="center|bottom"
        android:alpha="0.0"
        />

</FrameLayout>
Loading