Loading api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -48246,6 +48246,13 @@ package android.util { ctor public Base64OutputStream(java.io.OutputStream, int); } public final class CloseGuard { ctor public CloseGuard(); method public void close(); method public void open(@NonNull String); method public void warnIfOpen(); } @Deprecated public final class Config { field @Deprecated public static final boolean DEBUG = false; field @Deprecated public static final boolean LOGD = true; core/java/android/util/CloseGuard.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.util; import android.annotation.NonNull; /** * CloseGuard is a mechanism for flagging implicit finalizer cleanup of * resources that should have been cleaned up by explicit close * methods (aka "explicit termination methods" in Effective Java). * <p> * A simple example: <pre> {@code * class Foo { * * private final CloseGuard guard = CloseGuard.get(); * * ... * * public Foo() { * ...; * guard.open("cleanup"); * } * * public void cleanup() { * guard.close(); * ...; * } * * protected void finalize() throws Throwable { * try { * // Note that guard could be null if the constructor threw. * if (guard != null) { * guard.warnIfOpen(); * } * cleanup(); * } finally { * super.finalize(); * } * } * } * }</pre> * * In usage where the resource to be explicitly cleaned up is * allocated after object construction, CloseGuard protection can * be deferred. For example: <pre> {@code * class Bar { * * private final CloseGuard guard = CloseGuard.get(); * * ... * * public Bar() { * ...; * } * * public void connect() { * ...; * guard.open("cleanup"); * } * * public void cleanup() { * guard.close(); * ...; * Reference.reachabilityFence(this); * // For full correctness in the absence of a close() call, other methods may also need * // reachabilityFence() calls. * } * * protected void finalize() throws Throwable { * try { * // Note that guard could be null if the constructor threw. * if (guard != null) { * guard.warnIfOpen(); * } * cleanup(); * } finally { * super.finalize(); * } * } * } * }</pre> * * When used in a constructor, calls to {@code open} should occur at * the end of the constructor since an exception that would cause * abrupt termination of the constructor will mean that the user will * not have a reference to the object to cleanup explicitly. When used * in a method, the call to {@code open} should occur just after * resource acquisition. */ public final class CloseGuard { private final dalvik.system.CloseGuard mImpl; /** * Constructs a new CloseGuard instance. * {@link #open(String)} can be used to set up the instance to warn on failure to close. */ public CloseGuard() { mImpl = dalvik.system.CloseGuard.get(); } /** * Initializes the instance with a warning that the caller should have explicitly called the * {@code closeMethodName} method instead of relying on finalization. * * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen. * @throws NullPointerException if closeMethodName is null. */ public void open(@NonNull String closeMethodName) { mImpl.open(closeMethodName); } /** Marks this CloseGuard instance as closed to avoid warnings on finalization. */ public void close() { mImpl.close(); } /** * Logs a warning if the caller did not properly cleanup by calling an explicit close method * before finalization. */ public void warnIfOpen() { mImpl.warnIfOpen(); } } core/tests/coretests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ android_test { ], static_libs: [ "frameworks-base-testutils", "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport "core-tests-support", "android-common", "frameworks-core-util-lib", Loading core/tests/coretests/src/android/util/CloseGuardTest.java 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.util; import libcore.dalvik.system.CloseGuardSupport; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; /** Unit tests for {@link android.util.CloseGuard} */ public class CloseGuardTest { @Rule public final TestRule rule = CloseGuardSupport.getRule(); @Test public void testEnabled_NotOpen() throws Throwable { ResourceOwner owner = new ResourceOwner(); assertUnreleasedResources(owner, 0); } @Test public void testEnabled_OpenNotClosed() throws Throwable { ResourceOwner owner = new ResourceOwner(); owner.open(); assertUnreleasedResources(owner, 1); } @Test public void testEnabled_OpenThenClosed() throws Throwable { ResourceOwner owner = new ResourceOwner(); owner.open(); owner.close(); assertUnreleasedResources(owner, 0); } @Test(expected = NullPointerException.class) public void testOpen_withNullMethodName_throwsNPE() throws Throwable { CloseGuard closeGuard = new CloseGuard(); closeGuard.open(null); } private void assertUnreleasedResources(ResourceOwner owner, int expectedCount) throws Throwable { try { CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount); } finally { // Close the resource so that CloseGuard does not generate a warning for real when it // is actually finalized. owner.close(); } } /** * A test user of {@link CloseGuard}. */ private static class ResourceOwner { private final CloseGuard mCloseGuard; ResourceOwner() { mCloseGuard = new CloseGuard(); } public void open() { mCloseGuard.open("close"); } public void close() { mCloseGuard.close(); } /** * Make finalize public so that it can be tested directly without relying on garbage * collection to trigger it. */ @Override public void finalize() throws Throwable { mCloseGuard.warnIfOpen(); super.finalize(); } } } Loading
api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -48246,6 +48246,13 @@ package android.util { ctor public Base64OutputStream(java.io.OutputStream, int); } public final class CloseGuard { ctor public CloseGuard(); method public void close(); method public void open(@NonNull String); method public void warnIfOpen(); } @Deprecated public final class Config { field @Deprecated public static final boolean DEBUG = false; field @Deprecated public static final boolean LOGD = true;
core/java/android/util/CloseGuard.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.util; import android.annotation.NonNull; /** * CloseGuard is a mechanism for flagging implicit finalizer cleanup of * resources that should have been cleaned up by explicit close * methods (aka "explicit termination methods" in Effective Java). * <p> * A simple example: <pre> {@code * class Foo { * * private final CloseGuard guard = CloseGuard.get(); * * ... * * public Foo() { * ...; * guard.open("cleanup"); * } * * public void cleanup() { * guard.close(); * ...; * } * * protected void finalize() throws Throwable { * try { * // Note that guard could be null if the constructor threw. * if (guard != null) { * guard.warnIfOpen(); * } * cleanup(); * } finally { * super.finalize(); * } * } * } * }</pre> * * In usage where the resource to be explicitly cleaned up is * allocated after object construction, CloseGuard protection can * be deferred. For example: <pre> {@code * class Bar { * * private final CloseGuard guard = CloseGuard.get(); * * ... * * public Bar() { * ...; * } * * public void connect() { * ...; * guard.open("cleanup"); * } * * public void cleanup() { * guard.close(); * ...; * Reference.reachabilityFence(this); * // For full correctness in the absence of a close() call, other methods may also need * // reachabilityFence() calls. * } * * protected void finalize() throws Throwable { * try { * // Note that guard could be null if the constructor threw. * if (guard != null) { * guard.warnIfOpen(); * } * cleanup(); * } finally { * super.finalize(); * } * } * } * }</pre> * * When used in a constructor, calls to {@code open} should occur at * the end of the constructor since an exception that would cause * abrupt termination of the constructor will mean that the user will * not have a reference to the object to cleanup explicitly. When used * in a method, the call to {@code open} should occur just after * resource acquisition. */ public final class CloseGuard { private final dalvik.system.CloseGuard mImpl; /** * Constructs a new CloseGuard instance. * {@link #open(String)} can be used to set up the instance to warn on failure to close. */ public CloseGuard() { mImpl = dalvik.system.CloseGuard.get(); } /** * Initializes the instance with a warning that the caller should have explicitly called the * {@code closeMethodName} method instead of relying on finalization. * * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen. * @throws NullPointerException if closeMethodName is null. */ public void open(@NonNull String closeMethodName) { mImpl.open(closeMethodName); } /** Marks this CloseGuard instance as closed to avoid warnings on finalization. */ public void close() { mImpl.close(); } /** * Logs a warning if the caller did not properly cleanup by calling an explicit close method * before finalization. */ public void warnIfOpen() { mImpl.warnIfOpen(); } }
core/tests/coretests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ android_test { ], static_libs: [ "frameworks-base-testutils", "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport "core-tests-support", "android-common", "frameworks-core-util-lib", Loading
core/tests/coretests/src/android/util/CloseGuardTest.java 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.util; import libcore.dalvik.system.CloseGuardSupport; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; /** Unit tests for {@link android.util.CloseGuard} */ public class CloseGuardTest { @Rule public final TestRule rule = CloseGuardSupport.getRule(); @Test public void testEnabled_NotOpen() throws Throwable { ResourceOwner owner = new ResourceOwner(); assertUnreleasedResources(owner, 0); } @Test public void testEnabled_OpenNotClosed() throws Throwable { ResourceOwner owner = new ResourceOwner(); owner.open(); assertUnreleasedResources(owner, 1); } @Test public void testEnabled_OpenThenClosed() throws Throwable { ResourceOwner owner = new ResourceOwner(); owner.open(); owner.close(); assertUnreleasedResources(owner, 0); } @Test(expected = NullPointerException.class) public void testOpen_withNullMethodName_throwsNPE() throws Throwable { CloseGuard closeGuard = new CloseGuard(); closeGuard.open(null); } private void assertUnreleasedResources(ResourceOwner owner, int expectedCount) throws Throwable { try { CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount); } finally { // Close the resource so that CloseGuard does not generate a warning for real when it // is actually finalized. owner.close(); } } /** * A test user of {@link CloseGuard}. */ private static class ResourceOwner { private final CloseGuard mCloseGuard; ResourceOwner() { mCloseGuard = new CloseGuard(); } public void open() { mCloseGuard.open("close"); } public void close() { mCloseGuard.close(); } /** * Make finalize public so that it can be tested directly without relying on garbage * collection to trigger it. */ @Override public void finalize() throws Throwable { mCloseGuard.warnIfOpen(); super.finalize(); } } }