/*
 * Copyright (C) 2013 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.
 */

import java.lang.Runtime;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.PhantomReference;
import dalvik.system.VMRuntime;

public class Main {
    static Object deadlockLock = new Object();
    static VMRuntime runtime = VMRuntime.getRuntime();
    static volatile boolean aboutToDeadlock = false;
    static final long MAX_EXPECTED_GC_DURATION_MS = 2000;

    // Save ref as a static field to ensure it doesn't get GC'd before the
    // referent is enqueued.
    static PhantomReference ref = null;

    static class DeadlockingFinalizer {
        protected void finalize() throws Exception {
            aboutToDeadlock = true;
            synchronized (deadlockLock) { }
        }
    }

    private static void allocateDeadlockingFinalizer() {
        new DeadlockingFinalizer();
    }

    public static PhantomReference allocPhantom(ReferenceQueue<Object> queue) {
        return new PhantomReference(new Object(), queue);
    }

    // Test that calling registerNativeAllocation triggers a GC eventually
    // after a substantial number of registered native bytes.
    private static void checkRegisterNativeAllocation() throws Exception {
        long maxMem = Runtime.getRuntime().maxMemory();
        int size = (int)(maxMem / 32);
        int allocationCount = 256;

        ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
        ref = allocPhantom(queue);
        long total = 0;
        for (int i = 0; !ref.isEnqueued() && i < allocationCount; ++i) {
            runtime.registerNativeAllocation(size);
            total += size;

            // Sleep a little bit to ensure not all of the calls to
            // registerNativeAllocation complete while GC is in the process of
            // running.
            Thread.sleep(MAX_EXPECTED_GC_DURATION_MS / allocationCount);
        }

        // Wait up to MAX_EXPECTED_GC_DURATION_MS to give GC a chance to finish
        // running. If the reference isn't enqueued after that, then it is
        // pretty unlikely (though technically still possible) that GC was
        // triggered as intended.
        if (queue.remove(MAX_EXPECTED_GC_DURATION_MS) == null) {
            throw new RuntimeException("GC failed to complete");
        }

        while (total > 0) {
            runtime.registerNativeFree(size);
            total -= size;
        }
    }

    // Call registerNativeAllocation repeatedly at a high rate to trigger the case of blocking
    // registerNativeAllocation. Stop before we risk exhausting the finalizer timeout.
    private static void triggerBlockingRegisterNativeAllocation() throws Exception {
        final long startTime = System.currentTimeMillis();
        final long finalizerTimeoutMs = VMRuntime.getRuntime().getFinalizerTimeoutMs();
        final long quittingTime = startTime + finalizerTimeoutMs - MAX_EXPECTED_GC_DURATION_MS;
        long maxMem = Runtime.getRuntime().maxMemory();
        int size = (int)(maxMem / 5);
        int allocationCount = 10;

        long total = 0;
        for (int i = 0; i < allocationCount && System.currentTimeMillis() < quittingTime; ++i) {
            runtime.registerNativeAllocation(size);
            total += size;
        }

        while (total > 0) {
            runtime.registerNativeFree(size);
            total -= size;
        }
    }

    public static void main(String[] args) throws Exception {
        // Test that registerNativeAllocation triggers GC.
        // Run this a few times in a loop to reduce the chances that the test
        // is flaky and make sure registerNativeAllocation continues to work
        // after the first GC is triggered.
        for (int i = 0; i < 20; ++i) {
            checkRegisterNativeAllocation();
        }

        // Test that we don't get a deadlock if we call
        // registerNativeAllocation with a blocked finalizer.
        synchronized (deadlockLock) {
            allocateDeadlockingFinalizer();
            while (!aboutToDeadlock) {
                Runtime.getRuntime().gc();
            }

            // Do more allocations now that the finalizer thread is deadlocked so that we force
            // finalization and timeout.
            triggerBlockingRegisterNativeAllocation();
        }
        System.out.println("Test complete");
    }
}

