/*
 * Copyright (C) 2010 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 dalvik.system;

import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;

import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;

/**
 * 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 {
 *
 *       {@literal @}ReachabilitySensitive
 *       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 {
 *
 *       {@literal @}ReachabilitySensitive
 *       private final CloseGuard guard = CloseGuard.get();
 *
 *       ...
 *
 *       public Bar() {
 *           ...;
 *       }
 *
 *       public void connect() {
 *          ...;
 *          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>
 *
 * 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.
 *
 * The @ReachabilitySensitive annotation ensures that finalize() cannot be
 * called during the explicit call to cleanup(), prior to the guard.close call.
 * There is an extremely small chance that, for code that neglects to call
 * cleanup(), finalize() and thus cleanup() will be called while a method on
 * the object is still active, but the "this" reference is no longer required.
 * If missing cleanup() calls are expected, additional @ReachabilitySensitive
 * annotations or reachabilityFence() calls may be required.
 *
 * @hide
 */
@SystemApi(client = MODULE_LIBRARIES)
@libcore.api.IntraCoreApi
public final class CloseGuard {

    /**
     * True if collection of call-site information (the expensive operation
     * here)  and tracking via a Tracker (see below) are enabled.
     * Enabled by default so we can diagnose issues early in VM startup.
     * Note, however, that Android disables this early in its startup,
     * but enables it with DropBoxing for system apps on debug builds.
     */
    private static volatile boolean stackAndTrackingEnabled = true;

    /**
     * Hook for customizing how CloseGuard issues are reported.
     * Bypassed if stackAndTrackingEnabled was false when open was called.
     */
    private static volatile Reporter reporter = new DefaultReporter();

    /**
     * Hook for customizing how CloseGuard issues are tracked.
     */
    private static volatile Tracker currentTracker = null; // Disabled by default.

    private static final String MESSAGE = "A resource was acquired at attached stack trace but never released. " +
            "See java.io.Closeable for information on avoiding resource leaks.";

    /**
     * Returns a CloseGuard instance. {@code #open(String)} can be used to set
     * up the instance to warn on failure to close.
     *
     * @return {@link CloseGuard} instance.
     *
     * @hide
     */
    @UnsupportedAppUsage(trackingBug=111170242)
    @SystemApi(client = MODULE_LIBRARIES)
    @libcore.api.IntraCoreApi
    public static CloseGuard get() {
        return new CloseGuard();
    }

    /**
     * Enables/disables stack capture and tracking. A call stack is captured
     * during open(), and open/close events are reported to the Tracker, only
     * if enabled is true. If a stack trace was captured, the {@link
     * #getReporter() reporter} is informed of unclosed resources; otherwise a
     * one-line warning is logged.
     *
     * @param enabled whether stack capture and tracking is enabled.
     *
     * @hide
     */
    @UnsupportedAppUsage
    @SystemApi(client = MODULE_LIBRARIES)
    public static void setEnabled(boolean enabled) {
        CloseGuard.stackAndTrackingEnabled = enabled;
    }

    /**
     * True if CloseGuard stack capture and tracking are enabled.
     *
     * @hide
     */
    public static boolean isEnabled() {
        return stackAndTrackingEnabled;
    }

    /**
     * Used to replace default Reporter used to warn of CloseGuard
     * violations when stack tracking is enabled. Must be non-null.
     *
     * @param rep replacement for default Reporter.
     *
     * @hide
     */
    @UnsupportedAppUsage
    @SystemApi(client = MODULE_LIBRARIES)
    public static void setReporter(Reporter rep) {
        if (rep == null) {
            throw new NullPointerException("reporter == null");
        }
        CloseGuard.reporter = rep;
    }

    /**
     * Returns non-null CloseGuard.Reporter.
     *
     * @return CloseGuard's Reporter.
     *
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public static Reporter getReporter() {
        return reporter;
    }

    /**
     * Sets the {@link Tracker} that is notified when resources are allocated and released.
     * The Tracker is invoked only if CloseGuard {@link #isEnabled()} held when {@link #open()}
     * was called. A null argument disables tracking.
     *
     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
     * MUST NOT be used for any other purposes.
     *
     * @hide
     */
    public static void setTracker(Tracker tracker) {
        currentTracker = tracker;
    }

    /**
     * Returns {@link #setTracker(Tracker) last Tracker that was set}, or null to indicate
     * there is none.
     *
     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
     * MUST NOT be used for any other purposes.
     *
     * @hide
     */
    public static Tracker getTracker() {
        return currentTracker;
    }

    @UnsupportedAppUsage
    private CloseGuard() {}

    /**
     * {@code open} initializes the instance with a warning that the caller
     * should have explicitly called the {@code closer} method instead of
     * relying on finalization.
     *
     * @param closer non-null name of explicit termination method. Printed by warnIfOpen.
     * @throws NullPointerException if closer is null.
     *
     * @hide
     */
    @UnsupportedAppUsage(trackingBug=111170242)
    @SystemApi(client = MODULE_LIBRARIES)
    @libcore.api.IntraCoreApi
    public void open(String closer) {
        openWithCallSite(closer, null /* callsite */);
    }

    /**
     * Like {@link #open(String)}, but with explicit callsite string being passed in for better
     * performance.
     * <p>
     * This only has better performance than {@link #open(String)} if {@link #isEnabled()} returns {@code true}, which
     * usually shouldn't happen on release builds.
     *
     * @param closer Non-null name of explicit termination method. Printed by warnIfOpen.
     * @param callsite Non-null string uniquely identifying the callsite.
     *
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public void openWithCallSite(String closer, String callsite) {
        // always perform the check for valid API usage...
        if (closer == null) {
            throw new NullPointerException("closer == null");
        }
        // ...but avoid allocating an allocation stack if "disabled"
        if (!stackAndTrackingEnabled) {
            closerNameOrAllocationInfo = closer;
            return;
        }
        // Always record stack trace when tracker installed, which only happens in tests. Otherwise, skip expensive
        // stack trace creation when explicit callsite is passed in for better performance.
        Tracker tracker = currentTracker;
        if (callsite == null || tracker != null) {
            String message = "Explicit termination method '" + closer + "' not called";
            Throwable stack = new Throwable(message);
            closerNameOrAllocationInfo = stack;
            if (tracker != null) {
                tracker.open(stack);
            }
        } else {
            closerNameOrAllocationInfo = callsite;
        }
    }

    // We keep either an allocation stack containing the closer String or, when
    // in disabled state, just the closer String.
    // We keep them in a single field only to minimize overhead.
    private Object /* String or Throwable */ closerNameOrAllocationInfo;

    /**
     * Marks this CloseGuard instance as closed to avoid warnings on
     * finalization.
     *
     * @hide
     */
    @UnsupportedAppUsage
    @SystemApi(client = MODULE_LIBRARIES)
    @libcore.api.IntraCoreApi
    public void close() {
        Tracker tracker = currentTracker;
        if (tracker != null && closerNameOrAllocationInfo instanceof Throwable) {
            // Invoke tracker on close only if we invoked it on open. Tracker may have changed.
            tracker.close((Throwable) closerNameOrAllocationInfo);
        }
        closerNameOrAllocationInfo = null;
    }

    /**
     * Logs a warning if the caller did not properly cleanup by calling an
     * explicit close method before finalization. If CloseGuard was enabled
     * when the CloseGuard was created, passes the stacktrace associated with
     * the allocation to the current reporter. If it was not enabled, it just
     * directly logs a brief message.
     *
     * @hide
     */
    @UnsupportedAppUsage(trackingBug=111170242)
    @SystemApi(client = MODULE_LIBRARIES)
    @libcore.api.IntraCoreApi
    public void warnIfOpen() {
        if (closerNameOrAllocationInfo != null) {
            if (closerNameOrAllocationInfo instanceof Throwable) {
                reporter.report(MESSAGE, (Throwable) closerNameOrAllocationInfo);
            } else if (stackAndTrackingEnabled) {
                reporter.report(MESSAGE + " Callsite: " + closerNameOrAllocationInfo);
            } else {
                System.logW("A resource failed to call "
                        + (String) closerNameOrAllocationInfo + ". ");
            }
        }
    }


    /**
     * Interface to allow customization of tracking behaviour.
     *
     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
     * MUST NOT be used for any other purposes.
     *
     * @hide
     */
    public interface Tracker {
        void open(Throwable allocationSite);
        void close(Throwable allocationSite);
    }

    /**
     * Interface to allow customization of reporting behavior.
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public interface Reporter {
        /**
         *
         * @hide
         */
        @UnsupportedAppUsage
        @SystemApi(client = MODULE_LIBRARIES)
        void report(String message, Throwable allocationSite);

        /**
         *
         * @hide
         */
        @SystemApi(client = MODULE_LIBRARIES)
        default void report(String message) {}
    }

    /**
     * Default Reporter which reports CloseGuard violations to the log.
     */
    private static final class DefaultReporter implements Reporter {
        @UnsupportedAppUsage
        private DefaultReporter() {}

        @Override public void report (String message, Throwable allocationSite) {
            System.logW(message, allocationSite);
        }

        @Override
        public void report(String message) {
            System.logW(message);
        }
    }
}
