/*
 * 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 com.android.internal.net.ipsec.ike;

import static android.net.ipsec.ike.IkeManager.getIkeLog;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;

import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_CHILD;
import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_CHILD;
import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD;
import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_DELETE_IKE;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_DPD;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_INFO;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_MOBIKE;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_IKE;

import android.annotation.IntDef;
import android.content.Context;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionParams;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Comparator;
import java.util.PriorityQueue;

/**
 * IkeLocalRequestScheduler caches all local requests scheduled by an IKE Session and notify the IKE
 * Session to process the request when it is allowed.
 *
 * <p>LocalRequestScheduler is running on the IkeSessionStateMachine thread.
 */
public final class IkeLocalRequestScheduler {
    private static final String TAG = "IkeLocalRequestScheduler";

    @VisibleForTesting static final String LOCAL_REQUEST_WAKE_LOCK_TAG = "LocalRequestWakeLock";

    private static final int DEFAULT_REQUEST_QUEUE_SIZE = 1;

    private static final int REQUEST_ID_NOT_ASSIGNED = -1;

    // Local request that must be handled immediately. Ex: CMD_LOCAL_REQUEST_DELETE_IKE
    @VisibleForTesting static final int REQUEST_PRIORITY_URGENT = 0;

    // Local request that must be handled soon, but not necessarily immediately.
    // Ex: CMD_LOCAL_REQUEST_MOBIKE
    @VisibleForTesting static final int REQUEST_PRIORITY_HIGH = 1;

    // Local request that should be handled once nothing more urgent requires handling. Most
    // LocalRequests will have this priority.
    @VisibleForTesting static final int REQUEST_PRIORITY_NORMAL = 2;

    // Local request that has an unknown priority. This shouldn't happen in normal processing.
    @VisibleForTesting static final int REQUEST_PRIORITY_UNKNOWN = Integer.MAX_VALUE;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        REQUEST_PRIORITY_URGENT,
        REQUEST_PRIORITY_HIGH,
        REQUEST_PRIORITY_NORMAL,
        REQUEST_PRIORITY_UNKNOWN
    })
    @interface RequestPriority {}

    public static int SPI_NOT_INCLUDED = 0;

    private final PowerManager mPowerManager;

    private final PriorityQueue<LocalRequest> mRequestQueue =
            new PriorityQueue<>(DEFAULT_REQUEST_QUEUE_SIZE, new LocalRequestComparator());

    private final IProcedureConsumer mConsumer;

    private int mNextRequestId;

    /**
     * Construct an instance of IkeLocalRequestScheduler
     *
     * @param consumer the interface to initiate new procedure.
     */
    public IkeLocalRequestScheduler(IProcedureConsumer consumer, Context context) {
        mConsumer = consumer;
        mPowerManager = context.getSystemService(PowerManager.class);

        mNextRequestId = 0;
    }

    /** Add a new local request to the queue. */
    public void addRequest(LocalRequest request) {
        request.acquireWakeLock(mPowerManager);
        request.setRequestId(mNextRequestId++);
        mRequestQueue.offer(request);
    }

    /**
     * Notifies the scheduler that the caller is ready for a new procedure
     *
     * <p>Synchronously triggers the call to onNewProcedureReady.
     *
     * @return whether or not a new procedure was scheduled.
     */
    public boolean readyForNextProcedure() {
        if (!mRequestQueue.isEmpty()) {
            mConsumer.onNewProcedureReady(mRequestQueue.poll());
            return true;
        }
        return false;
    }

    /** Release WakeLocks of all LocalRequests in the queue */
    public void releaseAllLocalRequestWakeLocks() {
        for (LocalRequest req : mRequestQueue) {
            req.releaseWakeLock();
        }
        mRequestQueue.clear();
    }

    /**
     * This class represents the common information of procedures that will be locally initiated.
     */
    public abstract static class LocalRequest {
        public final int procedureType;

        // Priority of this LocalRequest. Note that a lower 'priority' means higher urgency.
        @RequestPriority private final int mPriority;

        // ID used to preserve insertion-order between requests in IkeLocalRequestScheduler with the
        // same priority. Set when the LocalRequest is added to the IkeLocalRequestScheduler.
        private int mRequestId = REQUEST_ID_NOT_ASSIGNED;
        private WakeLock mWakeLock;

        LocalRequest(int type, int priority) {
            validateTypeOrThrow(type);
            procedureType = type;
            mPriority = priority;
        }

        @VisibleForTesting
        int getPriority() {
            return mPriority;
        }

        private void setRequestId(int requestId) {
            mRequestId = requestId;
        }

        @VisibleForTesting
        int getRequestId() {
            return mRequestId;
        }

        /**
         * Acquire a WakeLock for the LocalRequest.
         *
         * <p>This method will only be called from IkeLocalRequestScheduler#addRequest or
         * IkeLocalRequestScheduler#addRequestAtFront
         */
        private void acquireWakeLock(PowerManager powerManager) {
            if (mWakeLock != null && mWakeLock.isHeld()) {
                getIkeLog().wtf(TAG, "This LocalRequest already acquired a WakeLock");
                return;
            }

            mWakeLock =
                    powerManager.newWakeLock(
                            PARTIAL_WAKE_LOCK,
                            TAG + LOCAL_REQUEST_WAKE_LOCK_TAG + "_" + procedureType);
            mWakeLock.setReferenceCounted(false);
            mWakeLock.acquire();
        }

        /** Release WakeLock of the LocalRequest */
        public void releaseWakeLock() {
            if (mWakeLock != null) {
                mWakeLock.release();
                mWakeLock = null;
            }
        }

        protected abstract void validateTypeOrThrow(int type);

        protected abstract boolean isChildRequest();
    }

    /** LocalRequestComparator is a comparator for comparing LocalRequest instances. */
    private class LocalRequestComparator implements Comparator<LocalRequest> {
        @Override
        public int compare(LocalRequest requestA, LocalRequest requestB) {
            int relativePriorities =
                    Integer.compare(requestA.getPriority(), requestB.getPriority());
            if (relativePriorities != 0) return relativePriorities;

            return Integer.compare(requestA.getRequestId(), requestB.getRequestId());
        }
    }

    /**
     * This class represents a user requested or internally scheduled IKE procedure that will be
     * initiated locally.
     */
    public static class IkeLocalRequest extends LocalRequest {
        public long remoteSpi;

        /** Schedule a request for an IKE SA that is identified by the remoteIkeSpi */
        private IkeLocalRequest(int type, long remoteIkeSpi, int priority) {
            super(type, priority);
            remoteSpi = remoteIkeSpi;
        }

        @Override
        protected void validateTypeOrThrow(int type) {
            if (type >= CMD_LOCAL_REQUEST_CREATE_IKE && type <= CMD_LOCAL_REQUEST_MOBIKE) return;
            throw new IllegalArgumentException("Invalid IKE procedure type: " + type);
        }

        @Override
        protected boolean isChildRequest() {
            return false;
        }
    }

    /**
     * This class represents a user requested or internally scheduled Child procedure that will be
     * initiated locally.
     */
    public static class ChildLocalRequest extends LocalRequest {
        public int remoteSpi;
        public final ChildSessionCallback childSessionCallback;
        public final ChildSessionParams childSessionParams;

        private ChildLocalRequest(
                int type,
                int remoteChildSpi,
                ChildSessionCallback childCallback,
                ChildSessionParams childParams,
                int priority) {
            super(type, priority);
            childSessionParams = childParams;
            childSessionCallback = childCallback;
            remoteSpi = remoteChildSpi;
        }

        @Override
        protected void validateTypeOrThrow(int type) {
            if (type >= CMD_LOCAL_REQUEST_CREATE_CHILD
                    && type <= CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE) {
                return;
            }

            throw new IllegalArgumentException("Invalid Child procedure type: " + type);
        }

        @Override
        protected boolean isChildRequest() {
            return true;
        }
    }

    /** Interface to initiate a new IKE procedure */
    public interface IProcedureConsumer {
        /**
         * Called when a new IKE procedure can be initiated.
         *
         * @param localRequest the request to be initiated.
         */
        void onNewProcedureReady(LocalRequest localRequest);
    }

    /** package-protected */
    static class LocalRequestFactory {
        /** Create a request for the IKE Session */
        IkeLocalRequest getIkeLocalRequest(int type) {
            return getIkeLocalRequest(type, SPI_NOT_INCLUDED);
        }

        /** Create a request for an IKE SA that is identified by the remoteIkeSpi */
        IkeLocalRequest getIkeLocalRequest(int type, long remoteIkeSpi) {
            return new IkeLocalRequest(type, remoteIkeSpi, procedureTypeToPriority(type));
        }

        /** Create a request for a Child Session that is identified by the childCallback */
        ChildLocalRequest getChildLocalRequest(
                int type, ChildSessionCallback childCallback, ChildSessionParams childParams) {
            return new ChildLocalRequest(
                    type,
                    SPI_NOT_INCLUDED,
                    childCallback,
                    childParams,
                    procedureTypeToPriority(type));
        }

        /** Create a request for a Child SA that is identified by the remoteChildSpi */
        ChildLocalRequest getChildLocalRequest(int type, int remoteChildSpi) {
            return new ChildLocalRequest(
                    type,
                    remoteChildSpi,
                    null /*childCallback*/,
                    null /*childParams*/,
                    procedureTypeToPriority(type));
        }

        /** Returns the request priority for the specified procedure type. */
        @VisibleForTesting
        @RequestPriority
        static int procedureTypeToPriority(int procedureType) {
            switch (procedureType) {
                case CMD_LOCAL_REQUEST_DELETE_IKE:
                    return REQUEST_PRIORITY_URGENT;

                case CMD_LOCAL_REQUEST_MOBIKE:
                case CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE:
                    return REQUEST_PRIORITY_HIGH;

                case CMD_LOCAL_REQUEST_CREATE_IKE: // Fallthrough
                case CMD_LOCAL_REQUEST_REKEY_IKE: // Fallthrough
                case CMD_LOCAL_REQUEST_INFO: // Fallthrough
                case CMD_LOCAL_REQUEST_DPD: // Fallthrough
                case CMD_LOCAL_REQUEST_CREATE_CHILD: // Fallthrough
                case CMD_LOCAL_REQUEST_DELETE_CHILD: // Fallthrough
                case CMD_LOCAL_REQUEST_REKEY_CHILD:
                    return REQUEST_PRIORITY_NORMAL;

                default:
                    // unknown procedure type - assign it the lowest priority
                    getIkeLog().wtf(TAG, "Unknown procedureType: " + procedureType);
                    return REQUEST_PRIORITY_UNKNOWN;
            }
        }
    }
}
