Skip to content

Commit

Permalink
Merge pull request #6873 from robolectric/piper_411169531
Browse files Browse the repository at this point in the history
Fix theme native object collection in Android S
  • Loading branch information
hoisie committed Nov 20, 2021
2 parents eb494e6 + 23ff946 commit 4d30193
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
Expand Up @@ -9,21 +9,30 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.ColorDrawable;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
import android.widget.Button;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.lang.ref.WeakReference;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.R;
import org.robolectric.Robolectric;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.res.android.Registries;
import org.robolectric.shadows.testing.TestActivity;
import org.robolectric.util.ReflectionHelpers;
import org.xmlpull.v1.XmlPullParser;

@RunWith(AndroidJUnit4.class)
Expand Down Expand Up @@ -272,6 +281,40 @@ public void shouldApplyFromStyleAttribute() {
assertThat(button.getLayoutParams().width).isEqualTo(42); // comes via style attr
}

@Test
@Config(minSdk = VERSION_CODES.N)
public void shouldFreeNativeObjectInRegistry() {
final AtomicLong themeId = new AtomicLong(0);
Supplier<Theme> themeSupplier =
() -> {
Theme theme = resources.newTheme();
long nativeId =
ReflectionHelpers.getField(ReflectionHelpers.getField(theme, "mThemeImpl"), "mTheme");
themeId.set(nativeId);
return theme;
};

WeakReference<Theme> weakRef = new WeakReference<>(themeSupplier.get());
awaitFinalized(weakRef);
assertThat(Registries.NATIVE_THEME9_REGISTRY.peekNativeObject(themeId.get())).isNull();
}

private static <T> void awaitFinalized(WeakReference<T> weakRef) {
final CountDownLatch latch = new CountDownLatch(1);
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5);
while (System.nanoTime() < deadline) {
if (weakRef.get() == null) {
return;
}
try {
System.gc();
latch.await(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
}

////////////////////////////

private XmlResourceParser getFirstElementAttrSet(int resId) throws Exception {
Expand Down
Expand Up @@ -3,6 +3,7 @@
import static android.os.Build.VERSION_CODES.P;
import static android.os.Build.VERSION_CODES.Q;
import static android.os.Build.VERSION_CODES.R;
import static android.os.Build.VERSION_CODES.S;
import static org.robolectric.res.android.ApkAssetsCookie.K_INVALID_COOKIE;
import static org.robolectric.res.android.ApkAssetsCookie.kInvalidCookie;
import static org.robolectric.res.android.Asset.SEEK_CUR;
Expand Down Expand Up @@ -1610,6 +1611,12 @@ protected static void nativeThemeDestroy(long theme_ptr) {
Registries.NATIVE_THEME9_REGISTRY.unregister(theme_ptr);
}

@Implementation(minSdk = S)
protected void releaseTheme(long ptr) {
Registries.NATIVE_THEME9_REGISTRY.unregister(ptr);
reflector(AssetManagerReflector.class, realAssetManager).releaseTheme(ptr);
}

// static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
// jint resid, jboolean force) {
@Implementation(minSdk = P)
Expand Down Expand Up @@ -1936,6 +1943,9 @@ interface AssetManagerReflector {
@Static
@Direct
void createSystemAssetsInZygoteLocked();

@Direct
void releaseTheme(long ptr);
}
}
; // namespace android

0 comments on commit 4d30193

Please sign in to comment.