/*
 * 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.net.ipsec.ike.SaProposal.DH_GROUP_NONE;
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;

import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.BUNDLE_KEY_CHILD_REMOTE_SPI;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_ALARM_FIRED;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_DELETE_CHILD;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_REKEY_CHILD;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.buildIkeAlarmIntent;
import static com.android.internal.net.ipsec.ike.message.IkeHeader.EXCHANGE_TYPE_CREATE_CHILD_SA;
import static com.android.internal.net.ipsec.ike.message.IkeHeader.EXCHANGE_TYPE_IKE_AUTH;
import static com.android.internal.net.ipsec.ike.message.IkeHeader.EXCHANGE_TYPE_INFORMATIONAL;
import static com.android.internal.net.ipsec.ike.message.IkeHeader.ExchangeType;
import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_REKEY_SA;
import static com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NOTIFY_TYPE_USE_TRANSPORT_MODE;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_CP;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_DELETE;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_KE;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_NONCE;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_NOTIFY;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_SA;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_TS_INITIATOR;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PAYLOAD_TYPE_TS_RESPONDER;
import static com.android.internal.net.ipsec.ike.message.IkePayload.PROTOCOL_ID_ESP;
import static com.android.internal.net.ipsec.ike.utils.IkeAlarmReceiver.ACTION_DELETE_CHILD;
import static com.android.internal.net.ipsec.ike.utils.IkeAlarmReceiver.ACTION_REKEY_CHILD;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.net.IpSecManager;
import android.net.IpSecManager.ResourceUnavailableException;
import android.net.IpSecManager.SecurityParameterIndex;
import android.net.IpSecManager.SpiUnavailableException;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
import android.net.ipsec.ike.ChildSessionParams;
import android.net.ipsec.ike.IkeTrafficSelector;
import android.net.ipsec.ike.SaProposal;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.exceptions.InvalidKeException;
import android.net.ipsec.ike.exceptions.InvalidSyntaxException;
import android.net.ipsec.ike.exceptions.NoValidProposalChosenException;
import android.net.ipsec.ike.exceptions.TemporaryFailureException;
import android.net.ipsec.ike.exceptions.TsUnacceptableException;
import android.os.Bundle;
import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.ipsec.ike.IkeLocalRequestScheduler.ChildLocalRequest;
import com.android.internal.net.ipsec.ike.IkeLocalRequestScheduler.LocalRequestFactory;
import com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IkeExchangeSubType;
import com.android.internal.net.ipsec.ike.SaRecord.ChildSaRecord;
import com.android.internal.net.ipsec.ike.SaRecord.SaLifetimeAlarmScheduler;
import com.android.internal.net.ipsec.ike.crypto.IkeCipher;
import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity;
import com.android.internal.net.ipsec.ike.crypto.IkeMacPrf;
import com.android.internal.net.ipsec.ike.message.IkeConfigPayload;
import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute;
import com.android.internal.net.ipsec.ike.message.IkeDeletePayload;
import com.android.internal.net.ipsec.ike.message.IkeKePayload;
import com.android.internal.net.ipsec.ike.message.IkeNoncePayload;
import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload;
import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload.NotifyType;
import com.android.internal.net.ipsec.ike.message.IkePayload;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.ChildProposal;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform;
import com.android.internal.net.ipsec.ike.message.IkeTsPayload;
import com.android.internal.net.ipsec.ike.utils.IpSecSpiGenerator;
import com.android.internal.net.ipsec.ike.utils.RandomnessFactory;
import com.android.internal.util.State;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * ChildSessionStateMachine tracks states and manages exchanges of this Child Session.
 *
 * <p>ChildSessionStateMachine has two types of states. One type are states where there is no
 * ongoing procedure affecting Child Session (non-procedure state), including Initial, Idle and
 * Receiving. All other states are "procedure" states which are named as follows:
 *
 * <pre>
 * State Name = [Procedure Type] + [Exchange Initiator] + [Exchange Type].
 * - An IKE procedure consists of one or two IKE exchanges:
 *      Procedure Type = {CreateChild | DeleteChild | Info | RekeyChild | SimulRekeyChild}.
 * - Exchange Initiator indicates whether local or remote peer is the exchange initiator:
 *      Exchange Initiator = {Local | Remote}
 * - Exchange type defines the function of this exchange.
 *      Exchange Type = {Create | Delete}
 * </pre>
 */
public class ChildSessionStateMachine extends AbstractSessionStateMachine {
    private static final String TAG = "ChildSessionStateMachine";

    private static final int SPI_NOT_REGISTERED = 0;

    private static final int CMD_GENERAL_BASE = CMD_PRIVATE_BASE;

    /** Receive request for negotiating first Child SA. */
    private static final int CMD_HANDLE_FIRST_CHILD_EXCHANGE = CMD_GENERAL_BASE + 1;
    /** Receive a request from the remote. */
    private static final int CMD_HANDLE_RECEIVED_REQUEST = CMD_GENERAL_BASE + 2;
    /** Receive a reponse from the remote. */
    private static final int CMD_HANDLE_RECEIVED_RESPONSE = CMD_GENERAL_BASE + 3;
    /** Kill Session and close all alive Child SAs immediately. */
    private static final int CMD_KILL_SESSION = CMD_GENERAL_BASE + 4;

    private static final SparseArray<String> CMD_TO_STR;

    static {
        CMD_TO_STR = new SparseArray<>();
        CMD_TO_STR.put(CMD_HANDLE_FIRST_CHILD_EXCHANGE, "Handle First Child");
        CMD_TO_STR.put(CMD_HANDLE_RECEIVED_REQUEST, "Rcv request");
        CMD_TO_STR.put(CMD_HANDLE_RECEIVED_RESPONSE, "Rcv response");
        CMD_TO_STR.put(CMD_KILL_SESSION, "Kill session");
    }

    private final Context mContext;
    private final int mIkeSessionId;
    private final AlarmManager mAlarmManager;
    private final IpSecManager mIpSecManager;

    private final RandomnessFactory mRandomFactory;
    /**
     * mIpSecSpiGenerator will be used by all Child SA creations in this Child Session to avoid SPI
     * collision in test mode.
     */
    private final IpSecSpiGenerator mIpSecSpiGenerator;

    private final LocalRequestFactory mLocalRequestFactory = new LocalRequestFactory();

    /** User provided configurations. */
    @VisibleForTesting final ChildSessionParams mChildSessionParams;

    private final ChildSessionCallback mUserCallback;

    /** Callback to notify IKE Session the state changes. */
    private final IChildSessionSmCallback mChildSmCallback;

    // TODO: Also store ChildSessionCallback for notifying users.

    /** Local address assigned on device. */
    @VisibleForTesting InetAddress mLocalAddress;
    /** Remote address configured by users. */
    @VisibleForTesting InetAddress mRemoteAddress;

    /**
     * UDP-Encapsulated socket that allows IPsec traffic to pass through a NAT. Null if UDP
     * encapsulation is not needed.
     */
    @VisibleForTesting @Nullable UdpEncapsulationSocket mUdpEncapSocket;

    /** Crypto parameters. Updated upon initial negotiation or IKE SA rekey. */
    @VisibleForTesting IkeMacPrf mIkePrf;

    @VisibleForTesting byte[] mSkD;

    /** Package private ChildSaProposal that represents the negotiated Child SA proposal. */
    @VisibleForTesting ChildSaProposal mSaProposal;

    /** Negotiated local Traffic Selector. */
    @VisibleForTesting IkeTrafficSelector[] mLocalTs;
    /** Negotiated remote Traffic Selector. */
    @VisibleForTesting IkeTrafficSelector[] mRemoteTs;

    @VisibleForTesting IkeCipher mChildCipher;
    @VisibleForTesting IkeMacIntegrity mChildIntegrity;

    /** Package private */
    @VisibleForTesting ChildSaRecord mCurrentChildSaRecord;
    /** Package private */
    @VisibleForTesting ChildSaRecord mLocalInitNewChildSaRecord;
    /** Package private */
    @VisibleForTesting ChildSaRecord mRemoteInitNewChildSaRecord;

    /** Package private */
    @VisibleForTesting ChildSaRecord mChildSaRecordSurviving;

    @VisibleForTesting final State mKillChildSessionParent = new KillChildSessionParent();

    @VisibleForTesting final State mInitial = new Initial();
    @VisibleForTesting final State mCreateChildLocalCreate = new CreateChildLocalCreate();
    @VisibleForTesting final State mIdle = new Idle();
    @VisibleForTesting final State mIdleWithDeferredRequest = new IdleWithDeferredRequest();
    @VisibleForTesting final State mClosedAndAwaitResponse = new ClosedAndAwaitResponse();
    @VisibleForTesting final State mDeleteChildLocalDelete = new DeleteChildLocalDelete();
    @VisibleForTesting final State mDeleteChildRemoteDelete = new DeleteChildRemoteDelete();
    @VisibleForTesting final State mRekeyChildLocalCreate = new RekeyChildLocalCreate();
    @VisibleForTesting final State mRekeyChildRemoteCreate = new RekeyChildRemoteCreate();
    @VisibleForTesting final State mRekeyChildLocalDelete = new RekeyChildLocalDelete();
    @VisibleForTesting final State mRekeyChildRemoteDelete = new RekeyChildRemoteDelete();
    @VisibleForTesting boolean mIsFirstChild;

    /**
     * Builds a new uninitialized ChildSessionStateMachine
     *
     * <p>Upon creation, this state machine will await either the handleFirstChildExchange
     * (IKE_AUTH), or the createChildSession (Additional child creation beyond the first child) to
     * be called, both of which must pass keying and SA information.
     *
     * <p>This two-stage initialization is required to allow race-free user interaction with the IKE
     * Session keyed on the child state machine callbacks.
     *
     * <p>Package private
     */
    ChildSessionStateMachine(
            Looper looper,
            Context context,
            int ikeSessionUniqueId,
            AlarmManager alarmManager,
            RandomnessFactory randomnessFactory,
            IpSecManager ipSecManager,
            IpSecSpiGenerator ipSecSpiGenerator,
            ChildSessionParams sessionParams,
            Executor userCbExecutor,
            ChildSessionCallback userCallback,
            IChildSessionSmCallback childSmCallback) {
        super(TAG, looper, userCbExecutor);

        mContext = context;
        mIkeSessionId = ikeSessionUniqueId;
        mAlarmManager = alarmManager;
        mRandomFactory = randomnessFactory;
        mIpSecManager = ipSecManager;
        mIpSecSpiGenerator = ipSecSpiGenerator;
        mChildSessionParams = sessionParams;

        mUserCallback = userCallback;
        mChildSmCallback = childSmCallback;

        addState(mKillChildSessionParent);

        addState(mInitial, mKillChildSessionParent);
        addState(mCreateChildLocalCreate, mKillChildSessionParent);
        addState(mIdle, mKillChildSessionParent);
        addState(mIdleWithDeferredRequest, mKillChildSessionParent);
        addState(mClosedAndAwaitResponse, mKillChildSessionParent);
        addState(mDeleteChildLocalDelete, mKillChildSessionParent);
        addState(mDeleteChildRemoteDelete, mKillChildSessionParent);
        addState(mRekeyChildLocalCreate, mKillChildSessionParent);
        addState(mRekeyChildRemoteCreate, mKillChildSessionParent);
        addState(mRekeyChildLocalDelete, mKillChildSessionParent);
        addState(mRekeyChildRemoteDelete, mKillChildSessionParent);

        setInitialState(mInitial);
    }

    /**
     * Interface for ChildSessionStateMachine to notify IkeSessionStateMachine of state changes.
     *
     * <p>Child Session may encounter an IKE Session fatal error in three cases with different
     * handling rules:
     *
     * <pre>
     * - When there is a fatal error in an inbound request, onOutboundPayloadsReady will be
     *   called first to send out an error notification and then onFatalIkeSessionError(false)
     *   will be called to locally close the IKE Session.
     * - When there is a fatal error in an inbound response, only onFatalIkeSessionError(true)
     *   will be called to notify the remote with a Delete request and then close the IKE Session.
     * - When there is an fatal error notification in an inbound response, only
     *   onFatalIkeSessionError(false) is called to close the IKE Session locally.
     * </pre>
     *
     * <p>Package private.
     */
    interface IChildSessionSmCallback {
        /** Notify that new Child SA is created. */
        void onChildSaCreated(int remoteSpi, ChildSessionStateMachine childSession);

        /** Notify that a Child SA is deleted. */
        void onChildSaDeleted(int remoteSpi);

        /** Schedule retry for a Create Child Request on the LocalRequestScheduler. */
        void scheduleRetryLocalRequest(ChildLocalRequest futureRequest);

        /** Notify the IKE Session to send out IKE message for this Child Session. */
        void onOutboundPayloadsReady(
                @ExchangeType int exchangeType,
                boolean isResp,
                List<IkePayload> payloadList,
                ChildSessionStateMachine childSession);

        /** Notify that a Child procedure has been finished. */
        void onProcedureFinished(ChildSessionStateMachine childSession);

        /**
         * Notify the IKE Session State Machine that this Child has been fully shut down.
         *
         * <p>This method MUST be called after the user callbacks have been fired, and MUST always
         * be called before the state machine can shut down.
         */
        void onChildSessionClosed(ChildSessionCallback userCallbacks);

        /**
         * Notify that a Child procedure has been finished and the IKE Session should close itself
         * because of a fatal error.
         *
         * <p>The IKE Session should send a Delete IKE request before closing when needsNotifyRemote
         * is true.
         */
        void onFatalIkeSessionError(boolean needsNotifyRemote);
    }

    /**
     * Receive requesting and responding payloads for negotiating first Child SA.
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     *
     * @param reqPayloads SA negotiation related payloads in IKE_AUTH request.
     * @param respPayloads SA negotiation related payloads in IKE_AUTH response.
     * @param localAddress The local (outer) address of the Child Session.
     * @param remoteAddress The remote (outer) address of the Child Session.
     * @param udpEncapSocket The socket to use for UDP encapsulation, or NULL if no encap needed.
     * @param ikePrf The pseudo-random function to use for key derivation
     * @param skD The key for which to derive new keying information from.
     */
    public void handleFirstChildExchange(
            List<IkePayload> reqPayloads,
            List<IkePayload> respPayloads,
            InetAddress localAddress,
            InetAddress remoteAddress,
            UdpEncapsulationSocket udpEncapSocket,
            IkeMacPrf ikePrf,
            byte[] skD) {

        this.mLocalAddress = localAddress;
        this.mRemoteAddress = remoteAddress;
        this.mUdpEncapSocket = udpEncapSocket;
        this.mIkePrf = ikePrf;
        this.mSkD = skD;
        mIsFirstChild = true;

        int spi = registerProvisionalChildAndGetSpi(respPayloads);
        sendMessage(
                CMD_HANDLE_FIRST_CHILD_EXCHANGE,
                new FirstChildNegotiationData(reqPayloads, respPayloads, spi));
    }

    /**
     * Initiate Create Child procedure.
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     *
     * @param localAddress The local (outer) address from which traffic will originate.
     * @param remoteAddress The remote (outer) address to which traffic will be sent.
     * @param udpEncapSocket The socket to use for UDP encapsulation, or NULL if no encap needed.
     * @param ikePrf The pseudo-random function to use for key derivation
     * @param skD The key for which to derive new keying information from.
     */
    public void createChildSession(
            InetAddress localAddress,
            InetAddress remoteAddress,
            UdpEncapsulationSocket udpEncapSocket,
            IkeMacPrf ikePrf,
            byte[] skD) {
        this.mLocalAddress = localAddress;
        this.mRemoteAddress = remoteAddress;
        this.mUdpEncapSocket = udpEncapSocket;
        this.mIkePrf = ikePrf;
        this.mSkD = skD;
        mIsFirstChild = false;

        sendMessage(CMD_LOCAL_REQUEST_CREATE_CHILD);
    }

    /**
     * Initiate Delete Child procedure.
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     */
    public void deleteChildSession() {
        sendMessage(CMD_LOCAL_REQUEST_DELETE_CHILD);
    }

    /**
     * Initiate Rekey Child procedure.
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     */
    public void rekeyChildSession() {
        sendMessage(CMD_LOCAL_REQUEST_REKEY_CHILD);
    }

    /**
     * Initiate Rekey Child procedure for MOBIKE (instead of migrating IPsec SAs).
     *
     * <p>This method should only be used as a fallback mode for devices that do not have
     * XFRM_MIGRATE kernel support.
     */
    public void rekeyChildSessionForMobike() {
        // TODO(b/172015298): implement MOBIKE rekey
    }

    /**
     * Kill Child Session and all alive Child SAs without doing IKE exchange.
     *
     * <p>It is usually called when IKE Session is being closed.
     */
    public void killSession() {
        sendMessage(CMD_KILL_SESSION);
    }

    /**
     * Receive a request
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     *
     * @param exchangeSubtype the exchange subtype of this inbound request.
     * @param exchangeType the exchange type in the request message.
     * @param payloadList the Child-procedure-related payload list in the request message that needs
     *     validation.
     */
    public void receiveRequest(
            @IkeExchangeSubType int exchangeSubtype,
            @ExchangeType int exchangeType,
            List<IkePayload> payloadList) {
        sendMessage(
                CMD_HANDLE_RECEIVED_REQUEST,
                new ReceivedRequest(exchangeSubtype, exchangeType, payloadList));
    }

    /**
     * Receive a response.
     *
     * <p>This method is called synchronously from IkeStateMachine. It proxies the synchronous call
     * as an asynchronous job to the ChildStateMachine handler.
     *
     * @param exchangeType the exchange type in the response message that needs validation.
     * @param payloadList the Child-procedure-related payload list in the response message that
     *     needs validation.
     */
    public void receiveResponse(@ExchangeType int exchangeType, List<IkePayload> payloadList) {
        if (!isAwaitingCreateResp()) {
            sendMessage(
                    CMD_HANDLE_RECEIVED_RESPONSE, new ReceivedResponse(exchangeType, payloadList));
        }

        // If we are waiting for a Create/RekeyCreate response and the received message contains SA
        // payload we need to register for this provisional Child.
        int spi = registerProvisionalChildAndGetSpi(payloadList);
        sendMessage(
                CMD_HANDLE_RECEIVED_RESPONSE,
                new ReceivedCreateResponse(exchangeType, payloadList, spi));
    }

    private boolean isAwaitingCreateResp() {
        return (getCurrentState() == mCreateChildLocalCreate
                || getCurrentState() == mRekeyChildLocalCreate);
    }

    /**
     * Update SK_d with provided value when IKE SA is rekeyed.
     *
     * <p>It MUST be only called at the end of Rekey IKE procedure, which guarantees this Child
     * Session is not in Create Child or Rekey Child procedure.
     *
     * @param skD the new skD in byte array.
     */
    public void setSkD(byte[] skD) {
        mSkD = skD;
    }

    /**
     * Register provisioning ChildSessionStateMachine in IChildSessionSmCallback
     *
     * <p>This method is for avoiding CHILD_SA_NOT_FOUND error in IkeSessionStateMachine when remote
     * peer sends request for delete/rekey this Child SA before ChildSessionStateMachine sends
     * FirstChildNegotiationData or Create response to itself.
     */
    private int registerProvisionalChildAndGetSpi(List<IkePayload> respPayloads) {
        IkeSaPayload saPayload =
                IkePayload.getPayloadForTypeInProvidedList(
                        PAYLOAD_TYPE_SA, IkeSaPayload.class, respPayloads);

        if (saPayload == null) return SPI_NOT_REGISTERED;

        // IkeSaPayload.Proposal stores SPI in long type so as to be applied to both 8-byte IKE SPI
        // and 4-byte Child SPI. Here we cast the stored SPI to int to represent a Child SPI.
        int remoteGenSpi = (int) (saPayload.proposalList.get(0).spi);
        mChildSmCallback.onChildSaCreated(remoteGenSpi, this);
        return remoteGenSpi;
    }

    private void replyErrorNotification(@NotifyType int notifyType) {
        replyErrorNotification(notifyType, new byte[0]);
    }

    private void replyErrorNotification(@NotifyType int notifyType, byte[] notifyData) {
        List<IkePayload> outPayloads = new ArrayList<>(1);
        IkeNotifyPayload notifyPayload = new IkeNotifyPayload(notifyType, notifyData);
        outPayloads.add(notifyPayload);

        mChildSmCallback.onOutboundPayloadsReady(
                EXCHANGE_TYPE_INFORMATIONAL, true /*isResp*/, outPayloads, this);
    }

    /** Notify users the deletion of a Child SA. MUST be called on user callback executor */
    private void onIpSecTransformPairDeleted(ChildSaRecord childSaRecord) {
        mUserCallback.onIpSecTransformDeleted(
                childSaRecord.getOutboundIpSecTransform(), IpSecManager.DIRECTION_OUT);
        mUserCallback.onIpSecTransformDeleted(
                childSaRecord.getInboundIpSecTransform(), IpSecManager.DIRECTION_IN);
    }

    /**
     * ReceivedRequest contains exchange subtype and payloads that are extracted from a request
     * message to the current Child procedure.
     */
    private static class ReceivedRequest {
        @IkeExchangeSubType public final int exchangeSubtype;
        @ExchangeType public final int exchangeType;
        public final List<IkePayload> requestPayloads;

        ReceivedRequest(
                @IkeExchangeSubType int eSubtype,
                @ExchangeType int eType,
                List<IkePayload> reqPayloads) {
            exchangeSubtype = eSubtype;
            exchangeType = eType;
            requestPayloads = reqPayloads;
        }
    }

    /**
     * ReceivedResponse contains exchange type and payloads that are extracted from a response
     * message to the current Child procedure.
     */
    private static class ReceivedResponse {
        @ExchangeType public final int exchangeType;
        public final List<IkePayload> responsePayloads;

        ReceivedResponse(@ExchangeType int eType, List<IkePayload> respPayloads) {
            exchangeType = eType;
            responsePayloads = respPayloads;
        }
    }

    private static class ReceivedCreateResponse extends ReceivedResponse {
        public final int registeredSpi;

        ReceivedCreateResponse(@ExchangeType int eType, List<IkePayload> respPayloads, int spi) {
            super(eType, respPayloads);
            registeredSpi = spi;
        }
    }

    /**
     * FirstChildNegotiationData contains payloads for negotiating first Child SA in IKE_AUTH
     * request and IKE_AUTH response and callback to notify IkeSessionStateMachine the SA
     * negotiation result.
     */
    private static class FirstChildNegotiationData extends ReceivedCreateResponse {
        public final List<IkePayload> requestPayloads;

        FirstChildNegotiationData(
                List<IkePayload> reqPayloads, List<IkePayload> respPayloads, int spi) {
            super(EXCHANGE_TYPE_IKE_AUTH, respPayloads, spi);
            requestPayloads = reqPayloads;
        }
    }

    /** Top level state for handling uncaught exceptions for all subclasses. */
    abstract class ExceptionHandler extends ExceptionHandlerBase {
        @Override
        protected void cleanUpAndQuit(RuntimeException e) {
            // TODO: b/140123526 Send a response if exception was caught when processing a request.

            // Clean up all SaRecords.
            closeAllSaRecords(false /*expectSaClosed*/);

            executeUserCallback(
                    () -> {
                        mUserCallback.onClosedExceptionally(new IkeInternalException(e));
                    });
            logWtf("Unexpected exception in " + getCurrentState().getName(), e);
            quitNow();
        }

        @Override
        protected String getCmdString(int cmd) {
            return CMD_TO_STR.get(cmd);
        }
    }

    /** Called when this StateMachine quits. */
    @Override
    protected void onQuitting() {
        // Clean up all SaRecords.
        closeAllSaRecords(true /*expectSaClosed*/);

        mChildSmCallback.onProcedureFinished(this);
        mChildSmCallback.onChildSessionClosed(mUserCallback);
    }

    private void closeAllSaRecords(boolean expectSaClosed) {
        closeChildSaRecord(mCurrentChildSaRecord, expectSaClosed);
        closeChildSaRecord(mLocalInitNewChildSaRecord, expectSaClosed);
        closeChildSaRecord(mRemoteInitNewChildSaRecord, expectSaClosed);

        mCurrentChildSaRecord = null;
        mLocalInitNewChildSaRecord = null;
        mRemoteInitNewChildSaRecord = null;
    }

    private void closeChildSaRecord(ChildSaRecord childSaRecord, boolean expectSaClosed) {
        if (childSaRecord == null) return;

        executeUserCallback(
                () -> {
                    onIpSecTransformPairDeleted(childSaRecord);
                });

        mChildSmCallback.onChildSaDeleted(childSaRecord.getRemoteSpi());
        childSaRecord.close();

        if (!expectSaClosed) return;

        logWtf(
                "ChildSaRecord with local SPI: "
                        + childSaRecord.getLocalSpi()
                        + " is not correctly closed.");
    }

    private void handleChildFatalError(Exception error) {
        IkeException ikeException =
                error instanceof IkeException
                        ? (IkeException) error
                        : new IkeInternalException(error);

        executeUserCallback(
                () -> {
                    mUserCallback.onClosedExceptionally(ikeException);
                });
        loge("Child Session fatal error", ikeException);

        // Clean up all SaRecords and quit
        closeAllSaRecords(false /*expectSaClosed*/);
        quitNow();
    }

    /**
     * This state handles the request to close Child Session immediately without initiating any
     * exchange.
     *
     * <p>Request for closing Child Session immediately is usually caused by the closing of IKE
     * Session. All states MUST be a child state of KillChildSessionParent to handle the closing
     * request.
     */
    private class KillChildSessionParent extends ExceptionHandler {
        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_KILL_SESSION:
                    executeUserCallback(
                            () -> {
                                mUserCallback.onClosed();
                            });

                    closeAllSaRecords(false /*expectSaClosed*/);

                    quitNow();
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * CreateChildLocalCreateBase represents the common information for a locally-initiated initial
     * Child SA negotiation for setting up this Child Session.
     */
    private abstract class CreateChildLocalCreateBase extends ExceptionHandler {
        protected void validateAndBuildChild(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType,
                int registeredSpi) {
            validateAndBuildChild(
                    reqPayloads,
                    respPayloads,
                    registeredSpi,
                    CreateChildSaHelper.validateAndNegotiateInitChild(
                            reqPayloads,
                            respPayloads,
                            exchangeType,
                            expectedExchangeType,
                            mChildSessionParams.isTransportMode(),
                            mIpSecSpiGenerator,
                            mRemoteAddress));
        }

        protected void validateAndBuildChild(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                int registeredSpi,
                CreateChildResult createChildResult) {
            switch (createChildResult.status) {
                case CREATE_STATUS_OK:
                    try {
                        setUpNegotiatedResult(createChildResult);

                        mCurrentChildSaRecord =
                                ChildSaRecord.makeChildSaRecord(
                                        mContext,
                                        reqPayloads,
                                        respPayloads,
                                        createChildResult.initSpi,
                                        createChildResult.respSpi,
                                        mLocalAddress,
                                        mRemoteAddress,
                                        mUdpEncapSocket,
                                        mIkePrf,
                                        mChildIntegrity,
                                        mChildCipher,
                                        mSkD,
                                        mChildSessionParams.isTransportMode(),
                                        true /*isLocalInit*/,
                                        buildSaLifetimeAlarmSched(
                                                createChildResult.respSpi.getSpi()));

                        ChildSessionConfiguration sessionConfig =
                                buildChildSessionConfigFromResp(createChildResult, respPayloads);
                        executeUserCallback(
                                () -> {
                                    mUserCallback.onIpSecTransformCreated(
                                            mCurrentChildSaRecord.getInboundIpSecTransform(),
                                            IpSecManager.DIRECTION_IN);
                                    mUserCallback.onIpSecTransformCreated(
                                            mCurrentChildSaRecord.getOutboundIpSecTransform(),
                                            IpSecManager.DIRECTION_OUT);
                                    mUserCallback.onOpened(sessionConfig);
                                });

                        transitionTo(mIdle);
                    } catch (GeneralSecurityException
                            | ResourceUnavailableException
                            | SpiUnavailableException
                            | IOException e) {
                        // #makeChildSaRecord failed.

                        // TODO: Initiate deletion
                        mChildSmCallback.onChildSaDeleted(createChildResult.respSpi.getSpi());
                        handleChildFatalError(e);
                    } finally {
                        // In the successful case the transform in ChildSaRecord has taken ownership
                        // of the SPI (in IpSecService), and will keep it alive.
                        createChildResult.initSpi.close();
                        createChildResult.respSpi.close();
                    }
                    break;
                case CREATE_STATUS_CHILD_ERROR_INVALID_MSG:
                    // TODO: Initiate deletion
                    handleCreationFailAndQuit(registeredSpi, createChildResult.exception);
                    break;
                case CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY:
                    handleCreationFailAndQuit(registeredSpi, createChildResult.exception);
                    break;
                default:
                    cleanUpAndQuit(
                            new IllegalStateException(
                                    "Unrecognized status: " + createChildResult.status));
            }
        }

        private void setUpNegotiatedResult(CreateChildResult createChildResult) {
            // Build crypto tools using negotiated ChildSaProposal. It is ensured by {@link
            // IkeSaPayload#getVerifiedNegotiatedChildProposalPair} that the negotiated
            // ChildSaProposal is valid. The negotiated ChildSaProposal has exactly one encryption
            // algorithm. When it has a combined-mode encryption algorithm, it either does not have
            // integrity algorithm or only has one NONE value integrity algorithm. When the
            // negotiated ChildSaProposal has a normal encryption algorithm, it either does not have
            // integrity algorithm or has one integrity algorithm with any supported value.

            mSaProposal = createChildResult.negotiatedProposal;
            mChildCipher = IkeCipher.create(mSaProposal.getEncryptionTransforms()[0]);
            if (mSaProposal.getIntegrityTransforms().length != 0
                    && mSaProposal.getIntegrityTransforms()[0].id
                            != SaProposal.INTEGRITY_ALGORITHM_NONE) {
                mChildIntegrity = IkeMacIntegrity.create(mSaProposal.getIntegrityTransforms()[0]);
            }

            mLocalTs = createChildResult.initTs;
            mRemoteTs = createChildResult.respTs;
        }

        private ChildSessionConfiguration buildChildSessionConfigFromResp(
                CreateChildResult createChildResult, List<IkePayload> respPayloads) {
            IkeConfigPayload configPayload =
                    IkePayload.getPayloadForTypeInProvidedList(
                            PAYLOAD_TYPE_CP, IkeConfigPayload.class, respPayloads);

            if (mChildSessionParams.isTransportMode()
                    || configPayload == null
                    || configPayload.configType != IkeConfigPayload.CONFIG_TYPE_REPLY) {
                if (configPayload != null) {
                    logw("Unexpected config payload. Config Type: " + configPayload.configType);
                }

                return new ChildSessionConfiguration(
                        Arrays.asList(createChildResult.initTs),
                        Arrays.asList(createChildResult.respTs));
            } else {
                return new ChildSessionConfiguration(
                        Arrays.asList(createChildResult.initTs),
                        Arrays.asList(createChildResult.respTs),
                        configPayload);
            }
        }

        private void handleCreationFailAndQuit(int registeredSpi, IkeException exception) {
            if (registeredSpi != SPI_NOT_REGISTERED) {
                mChildSmCallback.onChildSaDeleted(registeredSpi);
            }
            handleChildFatalError(exception);
        }
    }

    private String getIntentIdentifier(int remoteSpi) {
        return IkeSessionStateMachine.TAG + "_" + mIkeSessionId + "_" + TAG + "_" + remoteSpi;
    }

    private Message getIntentIkeSmMsg(int localRequestType, int remoteSpi) {
        Bundle spiBundle = new Bundle();
        spiBundle.putInt(BUNDLE_KEY_CHILD_REMOTE_SPI, remoteSpi);

        // This Message will eventually gets fired on the IKE session state machine's handler, since
        // the pendingIntent clears the target
        return obtainMessage(CMD_ALARM_FIRED, mIkeSessionId, localRequestType, spiBundle);
    }

    private SaLifetimeAlarmScheduler buildSaLifetimeAlarmSched(int remoteSpi) {
        PendingIntent deleteSaIntent =
                buildIkeAlarmIntent(
                        mContext,
                        ACTION_DELETE_CHILD,
                        getIntentIdentifier(remoteSpi),
                        getIntentIkeSmMsg(CMD_LOCAL_REQUEST_DELETE_CHILD, remoteSpi));
        PendingIntent rekeySaIntent =
                buildIkeAlarmIntent(
                        mContext,
                        ACTION_REKEY_CHILD,
                        getIntentIdentifier(remoteSpi),
                        getIntentIkeSmMsg(CMD_LOCAL_REQUEST_REKEY_CHILD, remoteSpi));

        return new SaLifetimeAlarmScheduler(
                mChildSessionParams.getHardLifetimeMsInternal(),
                mChildSessionParams.getSoftLifetimeMsInternal(),
                deleteSaIntent,
                rekeySaIntent,
                mAlarmManager);
    }

    /** Initial state of ChildSessionStateMachine. */
    class Initial extends CreateChildLocalCreateBase {
        List<IkePayload> mRequestPayloads;

        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_FIRST_CHILD_EXCHANGE:
                    FirstChildNegotiationData childNegotiationData =
                            (FirstChildNegotiationData) message.obj;
                    mRequestPayloads = childNegotiationData.requestPayloads;
                    List<IkePayload> respPayloads = childNegotiationData.responsePayloads;

                    // Negotiate Child SA. The exchangeType has been validated in
                    // IkeSessionStateMachine. Won't validate it again here.
                    validateAndBuildChild(
                            mRequestPayloads,
                            respPayloads,
                            EXCHANGE_TYPE_IKE_AUTH,
                            EXCHANGE_TYPE_IKE_AUTH,
                            childNegotiationData.registeredSpi);

                    return HANDLED;
                case CMD_LOCAL_REQUEST_CREATE_CHILD:
                    transitionTo(mCreateChildLocalCreate);
                    return HANDLED;
                case CMD_LOCAL_REQUEST_DELETE_CHILD:
                    // This may happen when creation has been rescheduled to be after deletion.
                    executeUserCallback(
                            () -> {
                                mUserCallback.onClosed();
                            });
                    quitNow();
                    return HANDLED;
                case CMD_FORCE_TRANSITION:
                    transitionTo((State) message.obj);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }

        @Override
        public void exitState() {
            CreateChildSaHelper.releaseSpiResources(mRequestPayloads);
        }
    }

    /**
     * CreateChildLocalCreate represents the state where Child Session initiates the Create Child
     * exchange.
     */
    class CreateChildLocalCreate extends CreateChildLocalCreateBase {
        private List<IkePayload> mRequestPayloads;

        @Override
        public void enterState() {
            try {
                mRequestPayloads =
                        CreateChildSaHelper.getInitChildCreateReqPayloads(
                                mRandomFactory,
                                mIpSecSpiGenerator,
                                mLocalAddress,
                                mChildSessionParams,
                                false /*isFirstChildSa*/);

                final ConfigAttribute[] configAttributes =
                        CreateChildSaHelper.getConfigAttributes(mChildSessionParams);
                if (configAttributes.length > 0) {
                    mRequestPayloads.add(
                            new IkeConfigPayload(
                                    false /*isReply*/, Arrays.asList(configAttributes)));
                }

                mChildSmCallback.onOutboundPayloadsReady(
                        EXCHANGE_TYPE_CREATE_CHILD_SA,
                        false /*isResp*/,
                        mRequestPayloads,
                        ChildSessionStateMachine.this);
            } catch (SpiUnavailableException | ResourceUnavailableException e) {
                // Fail to assign SPI
                handleChildFatalError(e);
            }
        }

        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_RESPONSE:
                    ReceivedCreateResponse rcvResp = (ReceivedCreateResponse) message.obj;
                    CreateChildResult createChildResult =
                            CreateChildSaHelper.validateAndNegotiateInitChild(
                                    mRequestPayloads,
                                    rcvResp.responsePayloads,
                                    rcvResp.exchangeType,
                                    EXCHANGE_TYPE_CREATE_CHILD_SA,
                                    mChildSessionParams.isTransportMode(),
                                    mIpSecSpiGenerator,
                                    mRemoteAddress);

                    // If the response includes the error notification for TEMPORARY_FAILURE, retry
                    // creating the Child.
                    if (isTemporaryFailure(createChildResult)) {
                        transitionTo(mInitial);

                        mChildSmCallback.scheduleRetryLocalRequest(
                                mLocalRequestFactory.getChildLocalRequest(
                                        CMD_LOCAL_REQUEST_CREATE_CHILD,
                                        mUserCallback,
                                        mChildSessionParams));
                        return HANDLED;
                    }

                    validateAndBuildChild(
                            mRequestPayloads,
                            rcvResp.responsePayloads,
                            rcvResp.registeredSpi,
                            createChildResult);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }

        @Override
        public void exitState() {
            CreateChildSaHelper.releaseSpiResources(mRequestPayloads);
        }

        private boolean isTemporaryFailure(CreateChildResult createChildResult) {
            if (createChildResult.status != CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY) {
                return false;
            }
            return createChildResult.exception instanceof TemporaryFailureException;
        }
    }

    /**
     * Idle represents a state when there is no ongoing IKE exchange affecting established Child SA.
     */
    class Idle extends ExceptionHandler {
        @Override
        public void enterState() {
            maybeNotifyIkeSessionStateMachine();
        }

        protected void maybeNotifyIkeSessionStateMachine() {
            mChildSmCallback.onProcedureFinished(ChildSessionStateMachine.this);
        }

        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_LOCAL_REQUEST_DELETE_CHILD:
                    transitionTo(mDeleteChildLocalDelete);
                    return HANDLED;
                case CMD_LOCAL_REQUEST_REKEY_CHILD:
                    transitionTo(mRekeyChildLocalCreate);
                    return HANDLED;
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;
                    switch (req.exchangeSubtype) {
                        case IKE_EXCHANGE_SUBTYPE_DELETE_CHILD:
                            deferMessage(message);
                            transitionTo(mDeleteChildRemoteDelete);
                            return HANDLED;
                        case IKE_EXCHANGE_SUBTYPE_REKEY_CHILD:
                            deferMessage(message);
                            transitionTo(mRekeyChildRemoteCreate);
                            return HANDLED;
                        default:
                            return NOT_HANDLED;
                    }
                case CMD_FORCE_TRANSITION: // Testing command
                    transitionTo((State) message.obj);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * This class is for handling the case when the previous procedure was finished by a new request
     *
     * <p>This state is the destination state when Child Session receives a new procedure request in
     * Rekey Delete. When entering this state, Child Session will process the deferred request as
     * Idle state does but will not notify IKE Session that Child Session has finished all the
     * procedures. It prevents IKE Session from going back to Idle state when its Child Session is
     * still busy.
     */
    class IdleWithDeferredRequest extends Idle {
        @Override
        public void maybeNotifyIkeSessionStateMachine() {
            // Do not notify IkeSessionStateMachine because Child Session needs to process the
            // deferred request and start a new procedure
        }
    }

    /**
     * This class represents the state that Child Session was closed by the remote while waiting for
     * a response.
     *
     * <p>This state is the destination state when Child Session receives a Delete request while
     * waitng for a Rekey Create response. When that happens, Child Session should close all IPsec
     * SAs and notify the user immediately to prevent security risk. Child Session also needs to
     * continue waiting for the response and keep its parent IKE Session retransmitting the request,
     * as required by the IKE spec.
     */
    private class ClosedAndAwaitResponse extends ExceptionHandler {
        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_RESPONSE:
                    // Do not need to verify the response since the Child Session is already closed
                    quitNow();
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * DeleteResponderBase represents all states after Child Session is established
     *
     * <p>All post-init states share common functionality of being able to respond to Delete Child
     * requests.
     */
    private abstract class DeleteResponderBase extends ExceptionHandler {
        /**
         * Check if the payload list has a Delete Payload that includes the remote SPI of the input
         * ChildSaRecord.
         */
        protected boolean hasRemoteChildSpiForDelete(
                List<IkePayload> payloads, ChildSaRecord expectedRecord) {
            List<IkeDeletePayload> delPayloads =
                    IkePayload.getPayloadListForTypeInProvidedList(
                            PAYLOAD_TYPE_DELETE, IkeDeletePayload.class, payloads);

            for (IkeDeletePayload delPayload : delPayloads) {
                for (int spi : delPayload.spisToDelete) {
                    if (spi == expectedRecord.getRemoteSpi()) return true;
                }
            }
            return false;
        }

        /**
         * Build and send payload list that has a Delete Payload that includes the local SPI of the
         * input ChildSaRecord.
         */
        protected void sendDeleteChild(ChildSaRecord childSaRecord, boolean isResp) {
            List<IkePayload> outIkePayloads = new ArrayList<>(1);
            outIkePayloads.add(new IkeDeletePayload(new int[] {childSaRecord.getLocalSpi()}));

            mChildSmCallback.onOutboundPayloadsReady(
                    EXCHANGE_TYPE_INFORMATIONAL,
                    isResp,
                    outIkePayloads,
                    ChildSessionStateMachine.this);
        }

        /**
         * Helper method for responding to a session deletion request
         *
         * <p>Note that this method expects that the session is keyed on the mCurrentChildSaRecord
         * and closing this Child SA indicates that the remote wishes to end the session as a whole.
         * As such, this should not be used in rekey cases where there is any ambiguity as to which
         * Child SA the session is reliant upon.
         *
         * <p>Note that this method will also quit the state machine
         */
        protected void handleDeleteSessionRequest(List<IkePayload> payloads) {
            if (!hasRemoteChildSpiForDelete(payloads, mCurrentChildSaRecord)) {
                cleanUpAndQuit(
                        new IllegalStateException(
                                "Found no remote SPI for mCurrentChildSaRecord in a Delete Child"
                                        + " request."));
            } else {

                executeUserCallback(
                        () -> {
                            mUserCallback.onClosed();
                            onIpSecTransformPairDeleted(mCurrentChildSaRecord);
                        });

                sendDeleteChild(mCurrentChildSaRecord, true /*isResp*/);

                mChildSmCallback.onChildSaDeleted(mCurrentChildSaRecord.getRemoteSpi());
                mCurrentChildSaRecord.close();
                mCurrentChildSaRecord = null;

                quitNow();
            }
        }

        protected void closeSessionAndNotifyUser(boolean quitStateMachine) {
            executeUserCallback(
                    () -> {
                        mUserCallback.onClosed();
                        onIpSecTransformPairDeleted(mCurrentChildSaRecord);
                    });

            mChildSmCallback.onChildSaDeleted(mCurrentChildSaRecord.getRemoteSpi());
            mCurrentChildSaRecord.close();
            mCurrentChildSaRecord = null;

            if (quitStateMachine) {
                quitNow();
            }
        }
    }

    /**
     * DeleteBase abstracts deletion handling for all states initiating and responding to a Delete
     * Child exchange
     *
     * <p>All subclasses of this state share common functionality that a deletion request is sent,
     * and the response is received.
     */
    private abstract class DeleteBase extends DeleteResponderBase {
        /** Validate payload types in Delete Child response. */
        protected void validateDeleteRespPayloadAndExchangeType(
                List<IkePayload> respPayloads, @ExchangeType int exchangeType)
                throws IkeProtocolException {

            if (exchangeType != EXCHANGE_TYPE_INFORMATIONAL) {
                throw new InvalidSyntaxException(
                        "Unexpected exchange type in Delete Child response: " + exchangeType);
            }

            for (IkePayload payload : respPayloads) {
                handlePayload:
                switch (payload.payloadType) {
                    case PAYLOAD_TYPE_DELETE:
                        // A Delete Payload is only required when it is not simultaneous deletion.
                        // Included Child SPIs are verified in the subclass to make sure the remote
                        // side is deleting the right SAs.
                        break handlePayload;
                    case PAYLOAD_TYPE_NOTIFY:
                        IkeNotifyPayload notify = (IkeNotifyPayload) payload;
                        if (!notify.isErrorNotify()) {
                            logw(
                                    "Unexpected or unknown status notification in Delete Child"
                                            + " response: "
                                            + notify.notifyType);
                            break handlePayload;
                        }

                        throw notify.validateAndBuildIkeException();
                    default:
                        logw(
                                "Unexpected payload type in Delete Child response: "
                                        + payload.payloadType);
                }
            }
        }
    }

    /**
     * DeleteChildLocalDelete represents the state where Child Session initiates the Delete Child
     * exchange.
     */
    class DeleteChildLocalDelete extends DeleteBase {
        private boolean mSimulDeleteDetected = false;

        @Override
        public void enterState() {
            mSimulDeleteDetected = false;
            sendDeleteChild(mCurrentChildSaRecord, false /*isResp*/);
        }

        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_RESPONSE:
                    try {
                        ReceivedResponse resp = (ReceivedResponse) message.obj;
                        validateDeleteRespPayloadAndExchangeType(
                                resp.responsePayloads, resp.exchangeType);

                        boolean currentSaSpiFound =
                                hasRemoteChildSpiForDelete(
                                        resp.responsePayloads, mCurrentChildSaRecord);
                        if (!currentSaSpiFound && !mSimulDeleteDetected) {
                            throw new InvalidSyntaxException(
                                    "Found no remote SPI in received Delete response.");
                        } else if (currentSaSpiFound && mSimulDeleteDetected) {
                            // As required by the RFC 7296, in simultaneous delete case, the remote
                            // side MUST NOT include SPI of mCurrentChildSaRecord. However, to
                            // provide better interoperatibility, IKE library will keep IKE Session
                            // alive and continue the deleting process.
                            logw(
                                    "Found remote SPI in the Delete response in a simultaneous"
                                            + " deletion case");
                        }

                        closeSessionAndNotifyUser(true /* quitStateMachine */);
                    } catch (IkeProtocolException e) {
                        // Shut down Child Session and notify users the error.
                        handleChildFatalError(e);
                    }
                    return HANDLED;
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;
                    switch (req.exchangeSubtype) {
                        case IKE_EXCHANGE_SUBTYPE_DELETE_CHILD:
                            // It has been verified in IkeSessionStateMachine that the incoming
                            // request can be ONLY for mCurrentChildSaRecord at this point.
                            if (!hasRemoteChildSpiForDelete(
                                    req.requestPayloads, mCurrentChildSaRecord)) {
                                // Program error
                                cleanUpAndQuit(
                                        new IllegalStateException(
                                                "Found no remote SPI for mCurrentChildSaRecord in"
                                                        + " a Delete request"));

                            } else {
                                mChildSmCallback.onOutboundPayloadsReady(
                                        EXCHANGE_TYPE_INFORMATIONAL,
                                        true /*isResp*/,
                                        new LinkedList<>(),
                                        ChildSessionStateMachine.this);
                                mSimulDeleteDetected = true;
                            }
                            return HANDLED;
                        case IKE_EXCHANGE_SUBTYPE_REKEY_CHILD:
                            replyErrorNotification(ERROR_TYPE_TEMPORARY_FAILURE);
                            return HANDLED;
                        default:
                            cleanUpAndQuit(
                                    new IllegalStateException(
                                            "Invalid exchange subtype for Child Session: "
                                                    + req.exchangeSubtype));
                            return HANDLED;
                    }
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * DeleteChildRemoteDelete represents the state where Child Session receives the Delete Child
     * request.
     */
    class DeleteChildRemoteDelete extends DeleteResponderBase {
        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;
                    if (req.exchangeSubtype == IKE_EXCHANGE_SUBTYPE_DELETE_CHILD) {
                        handleDeleteSessionRequest(req.requestPayloads);
                        return HANDLED;
                    }
                    return NOT_HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * RekeyChildLocalCreate represents the state where Child Session initiates the Rekey Child
     * exchange.
     *
     * <p>As indicated in RFC 7296 section 2.8, "when rekeying, the new Child SA SHOULD NOT have
     * different Traffic Selectors and algorithms than the old one."
     */
    class RekeyChildLocalCreate extends DeleteResponderBase {
        private List<IkePayload> mRequestPayloads;

        @Override
        public void enterState() {
            try {
                ChildSaProposal saProposal = mSaProposal;
                if (mIsFirstChild) {
                    saProposal = addDhGroupsFromChildSessionParamsIfAbsent();
                }

                // Build request with negotiated proposal and TS.
                mRequestPayloads =
                        CreateChildSaHelper.getRekeyChildCreateReqPayloads(
                                mRandomFactory,
                                mIpSecSpiGenerator,
                                mLocalAddress,
                                saProposal,
                                mLocalTs,
                                mRemoteTs,
                                mCurrentChildSaRecord.getLocalSpi(),
                                mChildSessionParams.isTransportMode());
                mChildSmCallback.onOutboundPayloadsReady(
                        EXCHANGE_TYPE_CREATE_CHILD_SA,
                        false /*isResp*/,
                        mRequestPayloads,
                        ChildSessionStateMachine.this);
            } catch (SpiUnavailableException | ResourceUnavailableException e) {
                loge("Fail to assign Child SPI. Schedule a retry for rekey Child");
                mCurrentChildSaRecord.rescheduleRekey(RETRY_INTERVAL_MS);
                transitionTo(mIdle);
            }
        }

        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;

                    if (req.exchangeSubtype == IKE_EXCHANGE_SUBTYPE_DELETE_CHILD) {
                        // Handle Delete request, notify users and do state transition to continue
                        // waiting for the response
                        sendDeleteChild(mCurrentChildSaRecord, true /*isResp*/);
                        closeSessionAndNotifyUser(false /* quitStateMachine */);
                        transitionTo(mClosedAndAwaitResponse);
                    } else {
                        replyErrorNotification(ERROR_TYPE_TEMPORARY_FAILURE);
                    }
                    return HANDLED;
                case CMD_HANDLE_RECEIVED_RESPONSE:
                    ReceivedCreateResponse resp = (ReceivedCreateResponse) message.obj;
                    CreateChildResult createChildResult =
                            CreateChildSaHelper.validateAndNegotiateRekeyChildResp(
                                    mRequestPayloads,
                                    resp.responsePayloads,
                                    resp.exchangeType,
                                    EXCHANGE_TYPE_CREATE_CHILD_SA,
                                    mChildSessionParams.isTransportMode(),
                                    mCurrentChildSaRecord,
                                    mIpSecSpiGenerator,
                                    mRemoteAddress);

                    switch (createChildResult.status) {
                        case CREATE_STATUS_OK:
                            try {
                                // Do not need to update TS because they are not changed.
                                mSaProposal = createChildResult.negotiatedProposal;

                                mLocalInitNewChildSaRecord =
                                        ChildSaRecord.makeChildSaRecord(
                                                mContext,
                                                mRequestPayloads,
                                                resp.responsePayloads,
                                                createChildResult.initSpi,
                                                createChildResult.respSpi,
                                                mLocalAddress,
                                                mRemoteAddress,
                                                mUdpEncapSocket,
                                                mIkePrf,
                                                mChildIntegrity,
                                                mChildCipher,
                                                mSkD,
                                                mChildSessionParams.isTransportMode(),
                                                true /*isLocalInit*/,
                                                buildSaLifetimeAlarmSched(
                                                        createChildResult.respSpi.getSpi()));

                                executeUserCallback(
                                        () -> {
                                            mUserCallback.onIpSecTransformCreated(
                                                    mLocalInitNewChildSaRecord
                                                            .getInboundIpSecTransform(),
                                                    IpSecManager.DIRECTION_IN);
                                            mUserCallback.onIpSecTransformCreated(
                                                    mLocalInitNewChildSaRecord
                                                            .getOutboundIpSecTransform(),
                                                    IpSecManager.DIRECTION_OUT);
                                        });

                                transitionTo(mRekeyChildLocalDelete);
                            } catch (GeneralSecurityException
                                    | ResourceUnavailableException
                                    | SpiUnavailableException
                                    | IOException e) {
                                // #makeChildSaRecord failed
                                handleProcessRespOrSaCreationFailAndQuit(resp.registeredSpi, e);
                            } finally {
                                // In the successful case the transform in ChildSaRecord has taken
                                // ownership of the SPI (in IpSecService), and will keep it alive.
                                createChildResult.initSpi.close();
                                createChildResult.respSpi.close();
                            }
                            break;
                        case CREATE_STATUS_CHILD_ERROR_INVALID_MSG:
                            handleProcessRespOrSaCreationFailAndQuit(
                                    resp.registeredSpi, createChildResult.exception);
                            break;
                        case CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY:
                            loge(
                                    "Received error notification for rekey Child. Schedule a"
                                            + " retry");
                            mCurrentChildSaRecord.rescheduleRekey(RETRY_INTERVAL_MS);

                            transitionTo(mIdle);
                            break;
                        default:
                            cleanUpAndQuit(
                                    new IllegalStateException(
                                            "Unrecognized status: " + createChildResult.status));
                    }
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }

        private void handleProcessRespOrSaCreationFailAndQuit(
                int registeredSpi, Exception exception) {
            // We don't retry rekey if failure was caused by invalid response or SA creation error.
            // Reason is there is no way to notify the remote side the old SA is still alive but the
            // new one has failed. Sending delete request for new SA indicates the rekey has
            // finished and the new SA has died.

            // TODO: Initiate deletion on newly created SA
            if (registeredSpi != SPI_NOT_REGISTERED) {
                mChildSmCallback.onChildSaDeleted(registeredSpi);
            }
            handleChildFatalError(exception);
        }

        @Override
        public void exitState() {
            CreateChildSaHelper.releaseSpiResources(mRequestPayloads);
        }
    }

    private ChildSaProposal addDhGroupsFromChildSessionParamsIfAbsent() {
        // DH groups are excluded for the first child. Add dh groups from child session params in
        // this case.
        if (mSaProposal.getDhGroups().size() != 0) {
            return mSaProposal;
        }

        Set<DhGroupTransform> dhGroupSet = new LinkedHashSet<>();
        for (SaProposal saProposal : mChildSessionParams.getSaProposals()) {
            if (!mSaProposal.isNegotiatedFromExceptDhGroup(saProposal)) continue;
            dhGroupSet.addAll(Arrays.asList(saProposal.getDhGroupTransforms()));
        }

        DhGroupTransform[] dhGroups = new DhGroupTransform[dhGroupSet.size()];
        dhGroupSet.toArray(dhGroups);

        return new ChildSaProposal(
                mSaProposal.getEncryptionTransforms(),
                mSaProposal.getIntegrityTransforms(),
                dhGroups,
                mSaProposal.getEsnTransforms());
    }

    /**
     * RekeyChildRemoteCreate represents the state where Child Session receives a Rekey Child
     * request.
     *
     * <p>As indicated in RFC 7296 section 2.8, "when rekeying, the new Child SA SHOULD NOT have
     * different Traffic Selectors and algorithms than the old one."
     *
     * <p>Errors in this exchange with no specific protocol error code will all be classified to use
     * NO_PROPOSAL_CHOSEN. The reason that we don't use NO_ADDITIONAL_SAS is because it indicates
     * "responder is unwilling to accept any more Child SAs on this IKE SA.", according to RFC 7296.
     * Sending this error may mislead the remote peer.
     */
    class RekeyChildRemoteCreate extends ExceptionHandler {
        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;

                    if (req.exchangeSubtype == IKE_EXCHANGE_SUBTYPE_REKEY_CHILD) {
                        handleCreateChildRequest(req);
                        return HANDLED;
                    }

                    return NOT_HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }

        private void handleCreateChildRequest(ReceivedRequest req) {
            List<IkePayload> reqPayloads = null;
            List<IkePayload> respPayloads = null;
            try {
                reqPayloads = req.requestPayloads;

                // Build a rekey response payload list with our previously selected proposal,
                // against which we will validate the received request. It is guaranteed in
                // IkeSessionStateMachine#getIkeExchangeSubType that a SA Payload is included in the
                // inbound request payload list.
                IkeSaPayload reqSaPayload =
                        IkePayload.getPayloadForTypeInProvidedList(
                                PAYLOAD_TYPE_SA, IkeSaPayload.class, reqPayloads);

                IkeKePayload reqKePayload =
                        IkePayload.getPayloadForTypeInProvidedList(
                                PAYLOAD_TYPE_KE, IkeKePayload.class, reqPayloads);

                ChildSaProposal saProposal = mSaProposal;

                // Try accepting a DH group requested during remote rekey for both first and
                // additional Child Sessions even if it is different from the previously negotiated
                // proposal.
                if (reqKePayload != null && isKePayloadAcceptable(reqKePayload)) {
                    saProposal = mSaProposal.getCopyWithAdditionalDhTransform(reqKePayload.dhGroup);
                }

                byte respProposalNumber = reqSaPayload.getNegotiatedProposalNumber(saProposal);

                respPayloads =
                        CreateChildSaHelper.getRekeyChildCreateRespPayloads(
                                mRandomFactory,
                                mIpSecSpiGenerator,
                                mLocalAddress,
                                respProposalNumber,
                                saProposal,
                                mLocalTs,
                                mRemoteTs,
                                mCurrentChildSaRecord.getLocalSpi(),
                                mChildSessionParams.isTransportMode());
            } catch (NoValidProposalChosenException e) {
                handleCreationFailureAndBackToIdle(e);
                return;
            } catch (SpiUnavailableException | ResourceUnavailableException e) {
                handleCreationFailureAndBackToIdle(
                        new NoValidProposalChosenException("Fail to assign inbound SPI", e));
                return;
            }

            CreateChildResult createChildResult =
                    CreateChildSaHelper.validateAndNegotiateRekeyChildRequest(
                            reqPayloads,
                            respPayloads,
                            req.exchangeType /*exchangeType*/,
                            EXCHANGE_TYPE_CREATE_CHILD_SA /*expectedExchangeType*/,
                            mChildSessionParams.isTransportMode(),
                            mIpSecSpiGenerator,
                            mRemoteAddress);

            switch (createChildResult.status) {
                case CREATE_STATUS_OK:
                    try {
                        // Do not need to update TS because they are not changed.
                        mSaProposal = createChildResult.negotiatedProposal;

                        mRemoteInitNewChildSaRecord =
                                ChildSaRecord.makeChildSaRecord(
                                        mContext,
                                        reqPayloads,
                                        respPayloads,
                                        createChildResult.initSpi,
                                        createChildResult.respSpi,
                                        mLocalAddress,
                                        mRemoteAddress,
                                        mUdpEncapSocket,
                                        mIkePrf,
                                        mChildIntegrity,
                                        mChildCipher,
                                        mSkD,
                                        mChildSessionParams.isTransportMode(),
                                        false /*isLocalInit*/,
                                        buildSaLifetimeAlarmSched(
                                                createChildResult.initSpi.getSpi()));

                        mChildSmCallback.onChildSaCreated(
                                mRemoteInitNewChildSaRecord.getRemoteSpi(),
                                ChildSessionStateMachine.this);

                        // To avoid traffic loss, outbound transform should only be applied once
                        // the remote has (implicitly) acknowledged our response via the
                        // delete-old-SA request. This will be performed in the finishRekey()
                        // method.
                        executeUserCallback(
                                () -> {
                                    mUserCallback.onIpSecTransformCreated(
                                            mRemoteInitNewChildSaRecord.getInboundIpSecTransform(),
                                            IpSecManager.DIRECTION_IN);
                                });

                        mChildSmCallback.onOutboundPayloadsReady(
                                EXCHANGE_TYPE_CREATE_CHILD_SA,
                                true /*isResp*/,
                                respPayloads,
                                ChildSessionStateMachine.this);

                        transitionTo(mRekeyChildRemoteDelete);
                    } catch (GeneralSecurityException
                            | ResourceUnavailableException
                            | SpiUnavailableException
                            | IOException e) {
                        // #makeChildSaRecord failed.
                        handleCreationFailureAndBackToIdle(
                                new NoValidProposalChosenException(
                                        "Error in Child SA creation", e));
                    } finally {
                        // In the successful case the transform in ChildSaRecord has taken ownership
                        // of the SPI (in IpSecService), and will keep it alive.
                        createChildResult.initSpi.close();
                        createChildResult.respSpi.close();
                    }
                    break;
                case CREATE_STATUS_CHILD_ERROR_INVALID_MSG:
                    IkeException error = createChildResult.exception;
                    if (error instanceof IkeProtocolException) {
                        handleCreationFailureAndBackToIdle((IkeProtocolException) error);
                    } else {
                        handleCreationFailureAndBackToIdle(
                                new NoValidProposalChosenException(
                                        "Error in validating Create Child request", error));
                    }
                    break;
                case CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY:
                    cleanUpAndQuit(
                            new IllegalStateException(
                                    "Unexpected processing status in Create Child request: "
                                            + createChildResult.status));
                    break;
                default:
                    cleanUpAndQuit(
                            new IllegalStateException(
                                    "Unrecognized status: " + createChildResult.status));
            }
        }

        private boolean isKePayloadAcceptable(IkeKePayload reqKePayload) {
            ChildSaProposal proposal =
                    mSaProposal.getCopyWithAdditionalDhTransform(reqKePayload.dhGroup);

            // Verify if this proposal is accepted by user
            for (SaProposal saProposal : mChildSessionParams.getSaProposals()) {
                if (proposal.isNegotiatedFrom(saProposal)) {
                    return true;
                }
            }

            return false;
        }

        private void handleCreationFailureAndBackToIdle(IkeProtocolException e) {
            loge("Received invalid Rekey Child request. Reject with error notification", e);

            ArrayList<IkePayload> payloads = new ArrayList<>(1);
            payloads.add(e.buildNotifyPayload());
            mChildSmCallback.onOutboundPayloadsReady(
                    EXCHANGE_TYPE_CREATE_CHILD_SA,
                    true /*isResp*/,
                    payloads,
                    ChildSessionStateMachine.this);

            transitionTo(mIdle);
        }
    }

    /**
     * RekeyChildDeleteBase represents common behaviours of deleting stage during rekeying Child SA.
     */
    abstract class RekeyChildDeleteBase extends DeleteBase {
        @Override
        public boolean processStateMessage(Message message) {
            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    try {
                        if (isOnNewSa((ReceivedRequest) message.obj)) {
                            finishRekey();
                            deferMessage(message);
                            transitionTo(mIdleWithDeferredRequest);
                            return HANDLED;
                        }
                        return NOT_HANDLED;
                    } catch (IllegalStateException e) {
                        cleanUpAndQuit(e);
                        return HANDLED;
                    }
                default:
                    return NOT_HANDLED;
            }
        }

        private boolean isOnNewSa(ReceivedRequest req) {
            switch (req.exchangeSubtype) {
                case IKE_EXCHANGE_SUBTYPE_DELETE_CHILD:
                    return hasRemoteChildSpiForDelete(req.requestPayloads, mChildSaRecordSurviving);
                case IKE_EXCHANGE_SUBTYPE_REKEY_CHILD:
                    return CreateChildSaHelper.hasRemoteChildSpiForRekey(
                            req.requestPayloads, mChildSaRecordSurviving);
                default:
                    throw new IllegalStateException(
                            "Invalid exchange subtype for Child Session: " + req.exchangeSubtype);
            }
        }

        // Rekey timer for old SA will be cancelled as part of the closing of the SA.
        protected void finishRekey() {
            executeUserCallback(
                    () -> {
                        onIpSecTransformPairDeleted(mCurrentChildSaRecord);
                    });

            mChildSmCallback.onChildSaDeleted(mCurrentChildSaRecord.getRemoteSpi());
            mCurrentChildSaRecord.close();

            mCurrentChildSaRecord = mChildSaRecordSurviving;

            mLocalInitNewChildSaRecord = null;
            mRemoteInitNewChildSaRecord = null;
            mChildSaRecordSurviving = null;
        }
    }

    /**
     * RekeyChildLocalDelete represents the deleting stage of a locally-initiated Rekey Child
     * procedure.
     */
    class RekeyChildLocalDelete extends RekeyChildDeleteBase {
        private boolean mSimulDeleteDetected;

        @Override
        public void enterState() {
            mSimulDeleteDetected = false;
            mChildSaRecordSurviving = mLocalInitNewChildSaRecord;
            sendDeleteChild(mCurrentChildSaRecord, false /*isResp*/);
        }

        @Override
        public boolean processStateMessage(Message message) {
            if (super.processStateMessage(message) == HANDLED) {
                return HANDLED;
            }

            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;

                    if (req.exchangeSubtype == IKE_EXCHANGE_SUBTYPE_DELETE_CHILD) {
                        // Reply with empty message during simultaneous deleting and keep waiting
                        // for Delete response.
                        mChildSmCallback.onOutboundPayloadsReady(
                                EXCHANGE_TYPE_INFORMATIONAL,
                                true /*isResp*/,
                                new ArrayList<>(),
                                ChildSessionStateMachine.this);
                        mSimulDeleteDetected = true;
                    } else {
                        replyErrorNotification(ERROR_TYPE_TEMPORARY_FAILURE);
                    }
                    return HANDLED;
                case CMD_HANDLE_RECEIVED_RESPONSE:
                    try {
                        ReceivedResponse resp = (ReceivedResponse) message.obj;
                        validateDeleteRespPayloadAndExchangeType(
                                resp.responsePayloads, resp.exchangeType);

                        boolean currentSaSpiFound =
                                hasRemoteChildSpiForDelete(
                                        resp.responsePayloads, mCurrentChildSaRecord);
                        if (!mSimulDeleteDetected && !currentSaSpiFound) {
                            loge(
                                    "Found no remote SPI for current SA in received Delete"
                                        + " response. Shutting down old SA and finishing rekey.");
                        }
                    } catch (IkeProtocolException e) {
                        loge(
                                "Received Delete response with invalid syntax or error"
                                    + " notifications. Shutting down old SA and finishing rekey.",
                                e);
                    }
                    finishRekey();
                    transitionTo(mIdle);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

    /**
     * RekeyChildRemoteDelete represents the deleting stage of a remotely-initiated Rekey Child
     * procedure.
     */
    class RekeyChildRemoteDelete extends RekeyChildDeleteBase {
        @Override
        public void enterState() {
            mChildSaRecordSurviving = mRemoteInitNewChildSaRecord;
            sendMessageDelayed(TIMEOUT_REKEY_REMOTE_DELETE, REKEY_DELETE_TIMEOUT_MS);
        }

        @Override
        public boolean processStateMessage(Message message) {
            if (super.processStateMessage(message) == HANDLED) {
                return HANDLED;
            }

            switch (message.what) {
                case CMD_HANDLE_RECEIVED_REQUEST:
                    ReceivedRequest req = (ReceivedRequest) message.obj;

                    if (req.exchangeSubtype == IKE_EXCHANGE_SUBTYPE_DELETE_CHILD) {
                        handleDeleteRequest(req.requestPayloads);

                    } else {
                        replyErrorNotification(ERROR_TYPE_TEMPORARY_FAILURE);
                    }
                    return HANDLED;
                case TIMEOUT_REKEY_REMOTE_DELETE:
                    // Receiving this signal means the remote side has received the outbound
                    // Rekey-Create response since no retransmissions were received during the
                    // waiting time. IKE library will assume the remote side has set up the new
                    // Child SA and finish the rekey procedure. Users should be warned there is
                    // a risk that the remote side failed to set up the new Child SA and all
                    // outbound IPsec traffic protected by new Child SA will be dropped.

                    // TODO:Consider finishing rekey procedure if the IKE Session receives a new
                    // request. Since window size is one, receiving a new request indicates the
                    // remote side has received the outbound Rekey-Create response

                    finishRekey();
                    transitionTo(mIdle);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }

        private void handleDeleteRequest(List<IkePayload> payloads) {
            if (!hasRemoteChildSpiForDelete(payloads, mCurrentChildSaRecord)) {
                // Request received on incorrect SA
                cleanUpAndQuit(
                        new IllegalStateException(
                                "Found no remote SPI for current SA in received Delete"
                                        + " response."));
            } else {
                sendDeleteChild(mCurrentChildSaRecord, true /*isResp*/);
                finishRekey();
                transitionTo(mIdle);
            }
        }

        @Override
        protected void finishRekey() {
            executeUserCallback(
                    () -> {
                        mUserCallback.onIpSecTransformCreated(
                                mRemoteInitNewChildSaRecord.getOutboundIpSecTransform(),
                                IpSecManager.DIRECTION_OUT);
                    });

            super.finishRekey();
        }

        @Override
        public void exitState() {
            removeMessages(TIMEOUT_REKEY_REMOTE_DELETE);
        }
    }

    /**
     * Package private helper class to generate IKE SA creation payloads, in both request and
     * response directions.
     */
    static class CreateChildSaHelper {
        /** Create payload list for creating the initial Child SA for this Child Session. */
        public static List<IkePayload> getInitChildCreateReqPayloads(
                RandomnessFactory randomFactory,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress localAddress,
                ChildSessionParams childSessionParams,
                boolean isFirstChildSa)
                throws SpiUnavailableException, ResourceUnavailableException {

            ChildSaProposal[] saProposals = childSessionParams.getSaProposalsInternal();

            if (isFirstChildSa) {
                for (int i = 0; i < saProposals.length; i++) {
                    saProposals[i] =
                            childSessionParams.getSaProposalsInternal()[i]
                                    .getCopyWithoutDhTransform();
                }
            }

            List<IkePayload> payloadList =
                    getChildCreatePayloads(
                            IkeSaPayload.createChildSaRequestPayload(
                                    saProposals, ipSecSpiGenerator, localAddress),
                            childSessionParams.getInboundTrafficSelectorsInternal(),
                            childSessionParams.getOutboundTrafficSelectorsInternal(),
                            childSessionParams.isTransportMode(),
                            isFirstChildSa,
                            randomFactory);

            return payloadList;
        }

        public static ConfigAttribute[] getConfigAttributes(ChildSessionParams params) {
            if (!params.isTransportMode()) {
                return ((TunnelModeChildSessionParams) params).getConfigurationAttributesInternal();
            }
            return new ConfigAttribute[0];
        }

        /** Create payload list as a rekey Child Session request. */
        public static List<IkePayload> getRekeyChildCreateReqPayloads(
                RandomnessFactory randomFactory,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress localAddress,
                ChildSaProposal currentProposal,
                IkeTrafficSelector[] currentLocalTs,
                IkeTrafficSelector[] currentRemoteTs,
                int localSpi,
                boolean isTransport)
                throws SpiUnavailableException, ResourceUnavailableException {
            List<IkePayload> payloads =
                    getChildCreatePayloads(
                            IkeSaPayload.createChildSaRequestPayload(
                                    new ChildSaProposal[] {currentProposal},
                                    ipSecSpiGenerator,
                                    localAddress),
                            currentLocalTs,
                            currentRemoteTs,
                            isTransport,
                            false /*isFirstChildSa*/,
                            randomFactory);

            payloads.add(
                    new IkeNotifyPayload(
                            PROTOCOL_ID_ESP, localSpi, NOTIFY_TYPE_REKEY_SA, new byte[0]));
            return payloads;
        }

        /** Create payload list as a rekey Child Session response. */
        public static List<IkePayload> getRekeyChildCreateRespPayloads(
                RandomnessFactory randomFactory,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress localAddress,
                byte proposalNumber,
                ChildSaProposal currentProposal,
                IkeTrafficSelector[] currentLocalTs,
                IkeTrafficSelector[] currentRemoteTs,
                int localSpi,
                boolean isTransport)
                throws SpiUnavailableException, ResourceUnavailableException {
            List<IkePayload> payloads =
                    getChildCreatePayloads(
                            IkeSaPayload.createChildSaResponsePayload(
                                    proposalNumber,
                                    currentProposal,
                                    ipSecSpiGenerator,
                                    localAddress),
                            currentRemoteTs /*initTs*/,
                            currentLocalTs /*respTs*/,
                            isTransport,
                            false /*isFirstChildSa*/,
                            randomFactory);

            payloads.add(
                    new IkeNotifyPayload(
                            PROTOCOL_ID_ESP, localSpi, NOTIFY_TYPE_REKEY_SA, new byte[0]));
            return payloads;
        }

        /** Create payload list for creating a new Child SA. */
        private static List<IkePayload> getChildCreatePayloads(
                IkeSaPayload saPayload,
                IkeTrafficSelector[] initTs,
                IkeTrafficSelector[] respTs,
                boolean isTransport,
                boolean isFirstChildSa,
                RandomnessFactory randomFactory)
                throws ResourceUnavailableException {
            List<IkePayload> payloadList = new ArrayList<>(5);

            payloadList.add(saPayload);
            payloadList.add(new IkeTsPayload(true /*isInitiator*/, initTs));
            payloadList.add(new IkeTsPayload(false /*isInitiator*/, respTs));

            if (!isFirstChildSa) {
                payloadList.add(new IkeNoncePayload(randomFactory));
            }

            DhGroupTransform[] dhGroups =
                    ((ChildProposal) saPayload.proposalList.get(0))
                            .saProposal.getDhGroupTransforms();
            if (dhGroups.length != 0 && dhGroups[0].id != DH_GROUP_NONE) {
                payloadList.add(new IkeKePayload(dhGroups[0].id, randomFactory));
            }

            if (isTransport) payloadList.add(new IkeNotifyPayload(NOTIFY_TYPE_USE_TRANSPORT_MODE));

            return payloadList;
        }

        /**
         * Validate the received response of initial Create Child SA exchange and return the
         * negotiation result.
         */
        public static CreateChildResult validateAndNegotiateInitChild(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType,
                boolean expectTransport,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress remoteAddress) {

            return validateAndNegotiateChild(
                    reqPayloads,
                    respPayloads,
                    exchangeType,
                    expectedExchangeType,
                    true /*isLocalInit*/,
                    expectTransport,
                    ipSecSpiGenerator,
                    remoteAddress);
        }

        /**
         * Validate the received rekey-create request against locally built response (based on
         * previously negotiated Child SA) and return the negotiation result.
         */
        public static CreateChildResult validateAndNegotiateRekeyChildRequest(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType,
                boolean expectTransport,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress remoteAddress) {

            // It is guaranteed that a Rekey-Notify Payload with remote SPI of current Child SA is
            // included in the reqPayloads. So we won't validate it again here.
            return validateAndNegotiateChild(
                    reqPayloads,
                    respPayloads,
                    exchangeType,
                    expectedExchangeType,
                    false /*isLocalInit*/,
                    expectTransport,
                    ipSecSpiGenerator,
                    remoteAddress);
        }

        /**
         * Validate the received rekey-create response against locally built request and previously
         * negotiated Child SA, and return the negotiation result.
         */
        public static CreateChildResult validateAndNegotiateRekeyChildResp(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType,
                boolean expectTransport,
                ChildSaRecord expectedChildRecord,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress remoteAddress) {
            // Validate rest of payloads and negotiate Child SA.
            CreateChildResult childResult =
                    validateAndNegotiateChild(
                            reqPayloads,
                            respPayloads,
                            exchangeType,
                            expectedExchangeType,
                            true /*isLocalInit*/,
                            expectTransport,
                            ipSecSpiGenerator,
                            remoteAddress);

            // TODO: Validate new Child SA does not have different Traffic Selectors

            return childResult;
        }

        /**
         * Check if SPI of Child SA that is expected to be rekeyed is included in the provided
         * payload list.
         */
        public static boolean hasRemoteChildSpiForRekey(
                List<IkePayload> payloads, ChildSaRecord expectedRecord) {
            List<IkeNotifyPayload> notifyPayloads =
                    IkePayload.getPayloadListForTypeInProvidedList(
                            IkePayload.PAYLOAD_TYPE_NOTIFY, IkeNotifyPayload.class, payloads);

            boolean hasExpectedRekeyNotify = false;
            for (IkeNotifyPayload notifyPayload : notifyPayloads) {
                if (notifyPayload.notifyType == NOTIFY_TYPE_REKEY_SA
                        && notifyPayload.spi == expectedRecord.getRemoteSpi()) {
                    hasExpectedRekeyNotify = true;
                    break;
                }
            }

            return hasExpectedRekeyNotify;
        }

        public static void releaseSpiResources(List<IkePayload> reqPayloads) {
            if (reqPayloads == null) {
                return;
            }

            IkeSaPayload saPayload =
                    IkePayload.getPayloadForTypeInProvidedList(
                            IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, reqPayloads);
            if (saPayload != null) {
                saPayload.releaseChildSpiResourcesIfExists();
            }
        }

        /** Validate the received payload list and negotiate Child SA. */
        private static CreateChildResult validateAndNegotiateChild(
                List<IkePayload> reqPayloads,
                List<IkePayload> respPayloads,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType,
                boolean isLocalInit,
                boolean expectTransport,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress remoteAddress) {
            List<IkePayload> inboundPayloads = isLocalInit ? respPayloads : reqPayloads;

            try {
                validatePayloadAndExchangeType(
                        inboundPayloads,
                        isLocalInit /*isResp*/,
                        exchangeType,
                        expectedExchangeType);
            } catch (InvalidSyntaxException e) {
                return new CreateChildResult(CREATE_STATUS_CHILD_ERROR_INVALID_MSG, e);
            }

            List<IkeNotifyPayload> notifyPayloads =
                    IkePayload.getPayloadListForTypeInProvidedList(
                            IkePayload.PAYLOAD_TYPE_NOTIFY,
                            IkeNotifyPayload.class,
                            inboundPayloads);

            boolean hasTransportNotify = false;
            for (IkeNotifyPayload notify : notifyPayloads) {
                if (notify.isErrorNotify()) {
                    try {
                        IkeProtocolException exception = notify.validateAndBuildIkeException();
                        if (isLocalInit) {
                            return new CreateChildResult(
                                    CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY, exception);
                        } else {
                            logw("Received unexpected error notification: " + notify.notifyType);
                        }
                    } catch (InvalidSyntaxException e) {
                        return new CreateChildResult(CREATE_STATUS_CHILD_ERROR_INVALID_MSG, e);
                    }
                }

                switch (notify.notifyType) {
                    case IkeNotifyPayload.NOTIFY_TYPE_ADDITIONAL_TS_POSSIBLE:
                        // TODO: Store it as part of negotiation results that can be retrieved
                        // by users.
                        break;
                    case IkeNotifyPayload.NOTIFY_TYPE_IPCOMP_SUPPORTED:
                        // Ignore
                        break;
                    case IkeNotifyPayload.NOTIFY_TYPE_USE_TRANSPORT_MODE:
                        hasTransportNotify = true;
                        break;
                    case IkeNotifyPayload.NOTIFY_TYPE_ESP_TFC_PADDING_NOT_SUPPORTED:
                        // Ignore
                        break;
                    case IkeNotifyPayload.NOTIFY_TYPE_REKEY_SA:
                        // Handled in Rekey State. Ignore here.
                        break;
                    default:
                        // Unknown and unexpected status notifications are ignored as per RFC7296.
                        logw(
                                "Received unknown or unexpected status notifications with notify"
                                        + " type: "
                                        + notify.notifyType);
                }
            }

            Pair<ChildProposal, ChildProposal> childProposalPair = null;
            try {
                IkeSaPayload reqSaPayload =
                        IkePayload.getPayloadForTypeInProvidedList(
                                IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, reqPayloads);
                IkeSaPayload respSaPayload =
                        IkePayload.getPayloadForTypeInProvidedList(
                                IkePayload.PAYLOAD_TYPE_SA, IkeSaPayload.class, respPayloads);

                // This method either throws exception or returns non-null pair that contains two
                // valid {@link ChildProposal} both with a {@link SecurityParameterIndex} allocated
                // inside.
                childProposalPair =
                        IkeSaPayload.getVerifiedNegotiatedChildProposalPair(
                                reqSaPayload, respSaPayload, ipSecSpiGenerator, remoteAddress);
                ChildSaProposal saProposal = childProposalPair.second.saProposal;

                validateKePayloads(inboundPayloads, isLocalInit /*isResp*/, saProposal);

                if (expectTransport != hasTransportNotify) {
                    throw new NoValidProposalChosenException(
                            "Failed the negotiation on Child SA mode (conflicting modes chosen).");
                }

                Pair<IkeTrafficSelector[], IkeTrafficSelector[]> tsPair =
                        validateAndGetNegotiatedTsPair(reqPayloads, respPayloads);

                return new CreateChildResult(
                        childProposalPair.first.getChildSpiResource(),
                        childProposalPair.second.getChildSpiResource(),
                        saProposal,
                        tsPair.first,
                        tsPair.second);
            } catch (IkeProtocolException
                    | ResourceUnavailableException
                    | SpiUnavailableException e) {
                if (childProposalPair != null) {
                    childProposalPair.first.getChildSpiResource().close();
                    childProposalPair.second.getChildSpiResource().close();
                }

                if (e instanceof InvalidSyntaxException) {
                    return new CreateChildResult(
                            CREATE_STATUS_CHILD_ERROR_INVALID_MSG, (InvalidSyntaxException) e);
                } else if (e instanceof IkeProtocolException) {
                    return new CreateChildResult(
                            CREATE_STATUS_CHILD_ERROR_INVALID_MSG,
                            new InvalidSyntaxException(
                                    "Processing error in received Create Child response", e));
                } else {
                    return new CreateChildResult(
                            CREATE_STATUS_CHILD_ERROR_INVALID_MSG, new IkeInternalException(e));
                }
            }
        }

        // Validate syntax to make sure all necessary payloads exist and exchange type is correct.
        private static void validatePayloadAndExchangeType(
                List<IkePayload> inboundPayloads,
                boolean isResp,
                @ExchangeType int exchangeType,
                @ExchangeType int expectedExchangeType)
                throws InvalidSyntaxException {
            boolean hasSaPayload = false;
            boolean hasKePayload = false;
            boolean hasNoncePayload = false;
            boolean hasTsInitPayload = false;
            boolean hasTsRespPayload = false;
            boolean hasErrorNotify = false;

            for (IkePayload payload : inboundPayloads) {
                switch (payload.payloadType) {
                    case PAYLOAD_TYPE_SA:
                        hasSaPayload = true;
                        break;
                    case PAYLOAD_TYPE_KE:
                        // Could not decide if KE Payload MUST or MUST NOT be included until SA
                        // negotiation is done.
                        hasKePayload = true;
                        break;
                    case PAYLOAD_TYPE_NONCE:
                        hasNoncePayload = true;
                        break;
                    case PAYLOAD_TYPE_TS_INITIATOR:
                        hasTsInitPayload = true;
                        break;
                    case PAYLOAD_TYPE_TS_RESPONDER:
                        hasTsRespPayload = true;
                        break;
                    case PAYLOAD_TYPE_NOTIFY:
                        if (((IkeNotifyPayload) payload).isErrorNotify()) hasErrorNotify = true;
                        // Do not have enough context to handle all notifications. Handle them
                        // together in higher layer.
                        break;
                    case PAYLOAD_TYPE_CP:
                        // Handled in child creation state. Note Child Session can only handle
                        // Config Payload in initial creation and can only handle a Config Reply.
                        // For interoperability, Config Payloads received in rekey creation
                        // or with other config types will be ignored.
                        break;
                    default:
                        logw(
                                "Received unexpected payload in Create Child SA message. Payload"
                                        + " type: "
                                        + payload.payloadType);
                }
            }

            // Do not need to check exchange type of a request because it has been already verified
            // in IkeSessionStateMachine
            if (isResp
                    && exchangeType != expectedExchangeType
                    && exchangeType != EXCHANGE_TYPE_INFORMATIONAL) {
                throw new InvalidSyntaxException("Received invalid exchange type: " + exchangeType);
            }

            if (exchangeType == EXCHANGE_TYPE_INFORMATIONAL
                    && (hasSaPayload
                            || hasKePayload
                            || hasNoncePayload
                            || hasTsInitPayload
                            || hasTsRespPayload)) {
                logw(
                        "Unexpected payload found in an INFORMATIONAL message: SA, KE, Nonce,"
                                + " TS-Initiator or TS-Responder");
            }

            if (isResp
                    && !hasErrorNotify
                    && (!hasSaPayload
                            || !hasNoncePayload
                            || !hasTsInitPayload
                            || !hasTsRespPayload)) {
                throw new InvalidSyntaxException(
                        "SA, Nonce, TS-Initiator or TS-Responder missing.");
            }
        }

        private static Pair<IkeTrafficSelector[], IkeTrafficSelector[]>
                validateAndGetNegotiatedTsPair(
                        List<IkePayload> reqPayloads, List<IkePayload> respPayloads)
                        throws TsUnacceptableException {
            IkeTrafficSelector[] initTs =
                    validateAndGetNegotiatedTs(reqPayloads, respPayloads, true /*isInitTs*/);
            IkeTrafficSelector[] respTs =
                    validateAndGetNegotiatedTs(reqPayloads, respPayloads, false /*isInitTs*/);

            return new Pair<IkeTrafficSelector[], IkeTrafficSelector[]>(initTs, respTs);
        }

        private static IkeTrafficSelector[] validateAndGetNegotiatedTs(
                List<IkePayload> reqPayloads, List<IkePayload> respPayloads, boolean isInitTs)
                throws TsUnacceptableException {
            int tsType = isInitTs ? PAYLOAD_TYPE_TS_INITIATOR : PAYLOAD_TYPE_TS_RESPONDER;
            IkeTsPayload reqPayload =
                    IkePayload.getPayloadForTypeInProvidedList(
                            tsType, IkeTsPayload.class, reqPayloads);
            IkeTsPayload respPayload =
                    IkePayload.getPayloadForTypeInProvidedList(
                            tsType, IkeTsPayload.class, respPayloads);

            if (!reqPayload.contains(respPayload)) {
                throw new TsUnacceptableException();
            }

            // It is guaranteed by decoding inbound TS Payload and constructing outbound TS Payload
            // that each TS Payload has at least one IkeTrafficSelector.
            return respPayload.trafficSelectors;
        }

        @VisibleForTesting
        static void validateKePayloads(
                List<IkePayload> inboundPayloads,
                boolean isResp,
                ChildSaProposal negotiatedProposal)
                throws IkeProtocolException {
            DhGroupTransform[] dhTransforms = negotiatedProposal.getDhGroupTransforms();

            if (dhTransforms.length > 1) {
                throw new IllegalArgumentException(
                        "Found multiple DH Group Transforms in the negotiated SA proposal");
            }
            boolean expectKePayload =
                    dhTransforms.length == 1 && dhTransforms[0].id != DH_GROUP_NONE;

            IkeKePayload kePayload =
                    IkePayload.getPayloadForTypeInProvidedList(
                            PAYLOAD_TYPE_KE, IkeKePayload.class, inboundPayloads);

            if (expectKePayload && (kePayload == null || dhTransforms[0].id != kePayload.dhGroup)) {
                if (isResp) {
                    throw new InvalidSyntaxException(
                            "KE Payload missing or has mismatched DH Group with the negotiated"
                                    + " proposal.");
                } else {
                    throw new InvalidKeException(dhTransforms[0].id);
                }

            } else if (!expectKePayload && kePayload != null && isResp) {
                // It is valid when the remote request proposed multiple DH Groups with a KE
                // payload, and the responder chose DH_GROUP_NONE.
                throw new InvalidSyntaxException("Received unexpected KE Payload.");
            }
        }

        private static void logw(String s) {
            getIkeLog().w(TAG, s);
        }
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        CREATE_STATUS_OK,
        CREATE_STATUS_CHILD_ERROR_INVALID_MSG,
        CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY
    })
    @interface CreateStatus {}

    /** The Child SA negotiation succeeds. */
    private static final int CREATE_STATUS_OK = 0;
    /** The inbound message is invalid in Child negotiation but is non-fatal for IKE Session. */
    private static final int CREATE_STATUS_CHILD_ERROR_INVALID_MSG = 1;
    /** The inbound message includes error notification that failed the Child negotiation. */
    private static final int CREATE_STATUS_CHILD_ERROR_RCV_NOTIFY = 2;

    private static class CreateChildResult {
        @CreateStatus public final int status;
        public final SecurityParameterIndex initSpi;
        public final SecurityParameterIndex respSpi;
        public final ChildSaProposal negotiatedProposal;
        public final IkeTrafficSelector[] initTs;
        public final IkeTrafficSelector[] respTs;
        public final IkeException exception;

        private CreateChildResult(
                @CreateStatus int status,
                SecurityParameterIndex initSpi,
                SecurityParameterIndex respSpi,
                ChildSaProposal negotiatedProposal,
                IkeTrafficSelector[] initTs,
                IkeTrafficSelector[] respTs,
                IkeException exception) {
            this.status = status;
            this.initSpi = initSpi;
            this.respSpi = respSpi;
            this.negotiatedProposal = negotiatedProposal;
            this.initTs = initTs;
            this.respTs = respTs;
            this.exception = exception;
        }

        /* Construct a CreateChildResult instance for a successful case. */
        CreateChildResult(
                SecurityParameterIndex initSpi,
                SecurityParameterIndex respSpi,
                ChildSaProposal negotiatedProposal,
                IkeTrafficSelector[] initTs,
                IkeTrafficSelector[] respTs) {
            this(
                    CREATE_STATUS_OK,
                    initSpi,
                    respSpi,
                    negotiatedProposal,
                    initTs,
                    respTs,
                    null /*exception*/);
        }

        /** Construct a CreateChildResult instance for an error case. */
        CreateChildResult(@CreateStatus int status, IkeException exception) {
            this(
                    status,
                    null /*initSpi*/,
                    null /*respSpi*/,
                    null /*negotiatedProposal*/,
                    null /*initTs*/,
                    null /*respTs*/,
                    exception);
        }
    }
}
