// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content.browser;

import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.util.SparseArray;

import org.chromium.base.Log;
import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.process_launcher.ChildProcessConnection;

import java.util.LinkedList;

/**
 * Manages oom bindings used to bound child services.
 * This object must only be accessed from the launcher thread.
 */
class BindingManagerImpl implements BindingManager {
    private static final String TAG = "cr_BindingManager";

    // Low reduce ratio of moderate binding.
    private static final float MODERATE_BINDING_LOW_REDUCE_RATIO = 0.25f;
    // High reduce ratio of moderate binding.
    private static final float MODERATE_BINDING_HIGH_REDUCE_RATIO = 0.5f;

    // Delay of 1 second used when removing temporary strong binding of a process (only on
    // non-low-memory devices).
    private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000;

    // Delays used when clearing moderate binding pool when onSentToBackground happens.
    private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 * 1000;

    // These fields allow to override the parameters for testing - see
    // createBindingManagerForTesting().
    private final boolean mIsLowMemoryDevice;

    private static class ModerateBindingPool implements ComponentCallbacks2 {
        // Stores the connections in MRU order.
        private final LinkedList<ManagedConnection> mConnections = new LinkedList<>();
        private final int mMaxSize;

        private Runnable mDelayedClearer;

        public ModerateBindingPool(int maxSize) {
            mMaxSize = maxSize;
        }

        @Override
        public void onTrimMemory(final int level) {
            ThreadUtils.assertOnUiThread();
            LauncherThread.post(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, mConnections.size());
                    if (mConnections.isEmpty()) {
                        return;
                    }
                    if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
                        reduce(MODERATE_BINDING_LOW_REDUCE_RATIO);
                    } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
                        reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO);
                    } else if (level == TRIM_MEMORY_UI_HIDDEN) {
                        // This will be handled by |mDelayedClearer|.
                        return;
                    } else {
                        removeAllConnections();
                    }
                }
            });
        }

        @Override
        public void onLowMemory() {
            ThreadUtils.assertOnUiThread();
            LauncherThread.post(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "onLowMemory: evict %d bindings", mConnections.size());
                    removeAllConnections();
                }
            });
        }

        @Override
        public void onConfigurationChanged(Configuration configuration) {}

        private void reduce(float reduceRatio) {
            int oldSize = mConnections.size();
            int newSize = (int) (oldSize * (1f - reduceRatio));
            Log.i(TAG, "Reduce connections from %d to %d", oldSize, newSize);
            removeOldConnections(oldSize - newSize);
            assert mConnections.size() == newSize;
        }

        void addConnection(ManagedConnection managedConnection) {
            managedConnection.addModerateBinding();
            if (managedConnection.mConnection.isModerateBindingBound()) {
                addConnectionImpl(managedConnection);
            } else {
                removeConnectionImpl(managedConnection);
            }
        }

        void removeConnection(ManagedConnection managedConnection) {
            removeConnectionImpl(managedConnection);
        }

        void removeAllConnections() {
            removeOldConnections(mConnections.size());
        }

        int size() {
            return mConnections.size();
        }

        private void addConnectionImpl(ManagedConnection managedConnection) {
            // Note that the size of connections is currently fairly small (20).
            // If it became bigger we should consider using an alternate data structure so we don't
            // have to traverse the list every time.

            // Remove the connection if it's already in the list, we'll add it at the head.
            mConnections.removeFirstOccurrence(managedConnection);
            if (mConnections.size() == mMaxSize) {
                // Make room for the connection we are about to add.
                removeOldConnections(1);
            }
            mConnections.add(0, managedConnection);
            assert mConnections.size() <= mMaxSize;
        }

        private void removeConnectionImpl(ManagedConnection managedConnection) {
            int index = mConnections.indexOf(managedConnection);
            if (index != -1) {
                ManagedConnection connection = mConnections.remove(index);
                connection.mConnection.removeModerateBinding();
            }
        }

        private void removeOldConnections(int numberOfConnections) {
            assert numberOfConnections <= mConnections.size();
            for (int i = 0; i < numberOfConnections; i++) {
                ManagedConnection connection = mConnections.removeLast();
                connection.mConnection.removeModerateBinding();
            }
        }

        void onSentToBackground(final boolean onTesting) {
            if (mConnections.isEmpty()) return;
            mDelayedClearer = new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "Release moderate connections: %d", mConnections.size());
                    if (!onTesting) {
                        RecordHistogram.recordCountHistogram(
                                "Android.ModerateBindingCount", mConnections.size());
                    }
                    removeAllConnections();
                }
            };
            LauncherThread.postDelayed(mDelayedClearer, MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS);
        }

        void onBroughtToForeground() {
            if (mDelayedClearer != null) {
                LauncherThread.removeCallbacks(mDelayedClearer);
                mDelayedClearer = null;
            }
        }
    }

    private ModerateBindingPool mModerateBindingPool;

    /**
     * Wraps ChildProcessConnection keeping track of additional information needed to manage the
     * bindings of the connection. It goes away when the connection goes away.
     */
    private class ManagedConnection {
        // The connection to the service.
        private final ChildProcessConnection mConnection;

        // True iff there is a strong binding kept on the service because it is working in
        // foreground.
        private boolean mInForeground;

        // Indicates there's a pending view in this connection that's about to become foreground.
        // This currently maps exactly to the initial binding.
        private boolean mBoostPriorityForPendingViews = true;

        // True iff there is a strong binding kept on the service because it was bound for the
        // application background period.
        private boolean mBoundForBackgroundPeriod;

        /** Adds a strong service binding. */
        private void addStrongBinding() {
            mConnection.addStrongBinding();
            if (mModerateBindingPool != null) mModerateBindingPool.removeConnection(this);
        }

        /** Removes a strong service binding. */
        private void removeStrongBinding(final boolean keepAsModerate) {
            // We have to fail gracefully if the strong binding is not present, as on low-end the
            // binding could have been removed by dropOomBindings() when a new service was started.
            if (!mConnection.isStrongBindingBound()) return;

            // This runnable performs the actual unbinding. It will be executed synchronously when
            // on low-end devices and posted with a delay otherwise.
            Runnable doUnbind = new Runnable() {
                @Override
                public void run() {
                    if (mConnection.isStrongBindingBound()) {
                        mConnection.removeStrongBinding();
                        if (keepAsModerate) {
                            addConnectionToModerateBindingPool(mConnection);
                        }
                    }
                }
            };

            if (mIsLowMemoryDevice) {
                doUnbind.run();
            } else {
                LauncherThread.postDelayed(doUnbind, DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS);
            }
        }

        /**
         * Adds connection to the moderate binding pool. No-op if the connection has a strong
         * binding.
         * @param connection The ChildProcessConnection to add to the moderate binding pool.
         */
        private void addConnectionToModerateBindingPool(ChildProcessConnection connection) {
            if (mModerateBindingPool != null && !connection.isStrongBindingBound()) {
                mModerateBindingPool.addConnection(ManagedConnection.this);
            }
        }

        /** Removes the moderate service binding. */
        private void removeModerateBinding() {
            if (!mConnection.isModerateBindingBound()) return;
            mConnection.removeModerateBinding();
        }

        /** Adds the moderate service binding. */
        private void addModerateBinding() {
            mConnection.addModerateBinding();
        }

        /**
         * Drops the service bindings. This is used on low-end to drop bindings of the current
         * service when a new one is used in foreground.
         */
        private void dropBindings() {
            assert mIsLowMemoryDevice;
            mConnection.dropOomBindings();
        }

        ManagedConnection(ChildProcessConnection connection) {
            mConnection = connection;
        }

        /**
         * Sets the visibility of the service, adding or removing the strong binding as needed.
         */
        void setPriority(boolean foreground, boolean boostForPendingViews) {
            // Always add bindings before removing them.
            if (!mInForeground && foreground) {
                addStrongBinding();
            }
            if (!mBoostPriorityForPendingViews && boostForPendingViews) {
                mConnection.addInitialBinding();
            }

            if (mInForeground && !foreground) {
                removeStrongBinding(true);
            }
            if (mBoostPriorityForPendingViews && !boostForPendingViews) {
                addConnectionToModerateBindingPool(mConnection);
                mConnection.removeInitialBinding();
            }

            mInForeground = foreground;
            mBoostPriorityForPendingViews = boostForPendingViews;
        }

        /**
         * Sets or removes additional binding when the service is main service during the embedder
         * background period.
         */
        void setBoundForBackgroundPeriod(boolean boundForBackgroundPeriod) {
            if (boundForBackgroundPeriod == mBoundForBackgroundPeriod) return;

            if (boundForBackgroundPeriod) {
                addStrongBinding();
            } else {
                removeStrongBinding(false);
            }
            mBoundForBackgroundPeriod = boundForBackgroundPeriod;
        }
    }

    private final SparseArray<ManagedConnection> mManagedConnections =
            new SparseArray<ManagedConnection>();

    // The connection that was most recently set as foreground (using setInForeground()). This is
    // used to add additional binding on it when the embedder goes to background. On low-end, this
    // is also used to drop process bindings when a new one is created, making sure that only one
    // renderer process at a time is protected from oom killing.
    private ManagedConnection mLastConnectionInForeground;

    // The connection bound with additional binding in onSentToBackground().
    private ManagedConnection mConnectionBoundForBackgroundPeriod;

    // Whether this instance is used on testing.
    private final boolean mOnTesting;

    /**
     * The constructor is private to hide parameters exposed for testing from the regular consumer.
     * Use factory methods to create an instance.
     */
    private BindingManagerImpl(boolean isLowMemoryDevice, boolean onTesting) {
        assert LauncherThread.runningOnLauncherThread();
        mIsLowMemoryDevice = isLowMemoryDevice;
        mOnTesting = onTesting;
    }

    public static BindingManagerImpl createBindingManager() {
        assert LauncherThread.runningOnLauncherThread();
        return new BindingManagerImpl(SysUtils.isLowEndDevice(), false);
    }

    /**
     * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays
     * set to 0, so that the tests don't need to deal with actual waiting.
     * @param isLowEndDevice true iff the created instance should apply low-end binding policies
     */
    public static BindingManagerImpl createBindingManagerForTesting(boolean isLowEndDevice) {
        assert LauncherThread.runningOnLauncherThread();
        return new BindingManagerImpl(isLowEndDevice, true);
    }

    @Override
    public void addNewConnection(int pid, ChildProcessConnection connection) {
        assert LauncherThread.runningOnLauncherThread();
        // This will reset the previous entry for the pid in the unlikely event of the OS
        // reusing renderer pids.
        mManagedConnections.put(pid, new ManagedConnection(connection));
    }

    @Override
    public void setPriority(int pid, boolean foreground, boolean boostForPendingViews) {
        assert LauncherThread.runningOnLauncherThread();
        ManagedConnection managedConnection = mManagedConnections.get(pid);
        if (managedConnection == null) {
            Log.d(TAG, "Cannot setPriority() - never saw a connection for the pid: %d", pid);
            return;
        }

        if (foreground && mIsLowMemoryDevice && mLastConnectionInForeground != null
                && mLastConnectionInForeground != managedConnection) {
            mLastConnectionInForeground.dropBindings();
        }

        managedConnection.setPriority(foreground, boostForPendingViews);
        if (foreground) mLastConnectionInForeground = managedConnection;
    }

    @Override
    public void onSentToBackground() {
        assert LauncherThread.runningOnLauncherThread();
        assert mConnectionBoundForBackgroundPeriod == null;
        // mLastConnectionInForeground can be null at this point as the embedding application could
        // be used in foreground without spawning any renderers.
        if (mLastConnectionInForeground != null) {
            mLastConnectionInForeground.setBoundForBackgroundPeriod(true);
            mConnectionBoundForBackgroundPeriod = mLastConnectionInForeground;
        }
        if (mModerateBindingPool != null) mModerateBindingPool.onSentToBackground(mOnTesting);
    }

    @Override
    public void onBroughtToForeground() {
        assert LauncherThread.runningOnLauncherThread();
        if (mConnectionBoundForBackgroundPeriod != null) {
            mConnectionBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false);
            mConnectionBoundForBackgroundPeriod = null;
        }
        if (mModerateBindingPool != null) mModerateBindingPool.onBroughtToForeground();
    }

    @Override
    public void removeConnection(int pid) {
        assert LauncherThread.runningOnLauncherThread();
        ManagedConnection managedConnection = mManagedConnections.get(pid);
        if (managedConnection == null) return;

        mManagedConnections.remove(pid);
        if (mLastConnectionInForeground == managedConnection) {
            mLastConnectionInForeground = null;
        }
        if (mConnectionBoundForBackgroundPeriod == managedConnection) {
            mConnectionBoundForBackgroundPeriod = null;
        }
        if (mModerateBindingPool != null) mModerateBindingPool.removeConnection(managedConnection);
    }

    /** @return true iff the connection reference is no longer held */
    @VisibleForTesting
    public boolean isConnectionCleared(int pid) {
        assert LauncherThread.runningOnLauncherThread();
        return mManagedConnections.get(pid) == null;
    }

    @Override
    public void startModerateBindingManagement(Context context, int maxSize) {
        assert LauncherThread.runningOnLauncherThread();
        if (mIsLowMemoryDevice) return;

        if (mModerateBindingPool == null) {
            Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize);
            mModerateBindingPool = new ModerateBindingPool(maxSize);
            if (context != null) {
                // Note that it is safe to call Context.registerComponentCallbacks from a background
                // thread.
                context.registerComponentCallbacks(mModerateBindingPool);
            }
        }
    }

    @Override
    public void releaseAllModerateBindings() {
        assert LauncherThread.runningOnLauncherThread();
        if (mModerateBindingPool != null) {
            Log.i(TAG, "Release all moderate bindings: %d", mModerateBindingPool.size());
            mModerateBindingPool.removeAllConnections();
        }
    }
}
