/*
 * Copyright 2017 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 android.hardware.location;

import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

/**
 * @hide
 */
@SystemApi
public final class NanoAppBinary implements Parcelable {
    private static final String TAG = "NanoAppBinary";

    /*
     * The contents of the app binary.
     */
    private byte[] mNanoAppBinary;

    /*
     * Contents of the nanoapp binary header.
     *
     * Only valid if mHasValidHeader is true.
     * See nano_app_binary_t in context_hub.h for details.
     */
    private int mHeaderVersion;
    private int mMagic;
    private long mNanoAppId;
    private int mNanoAppVersion;
    private int mFlags;
    private long mHwHubType;
    private byte mTargetChreApiMajorVersion;
    private byte mTargetChreApiMinorVersion;

    private boolean mHasValidHeader = false;

    /*
     * The header version used to parse the binary in parseBinaryHeader().
     */
    private static final int EXPECTED_HEADER_VERSION = 1;

    /*
     * The magic value expected in the header as defined in context_hub.h.
     */
    private static final int EXPECTED_MAGIC_VALUE =
            (((int) 'N' <<  0) | ((int) 'A' <<  8) | ((int) 'N' << 16) | ((int) 'O' << 24));

    /*
     * Byte order established in context_hub.h
     */
    private static final ByteOrder HEADER_ORDER = ByteOrder.LITTLE_ENDIAN;

    /*
     * The size of the header in bytes as defined in context_hub.h.
     */
    private static final int HEADER_SIZE_BYTES = 40;

    /*
     * The bit fields for mFlags as defined in context_hub.h.
     */
    private static final int NANOAPP_SIGNED_FLAG_BIT = 0x1;
    private static final int NANOAPP_ENCRYPTED_FLAG_BIT = 0x2;

    public NanoAppBinary(byte[] appBinary) {
        mNanoAppBinary = appBinary;
        parseBinaryHeader();
    }

    /*
     * Parses the binary header and populates its field using mNanoAppBinary.
     */
    private void parseBinaryHeader() {
        ByteBuffer buf = ByteBuffer.wrap(mNanoAppBinary).order(HEADER_ORDER);

        mHasValidHeader = false;
        try {
            mHeaderVersion = buf.getInt();
            if (mHeaderVersion != EXPECTED_HEADER_VERSION) {
                Log.e(TAG, "Unexpected header version " + mHeaderVersion + " while parsing header"
                        + " (expected " + EXPECTED_HEADER_VERSION + ")");
                return;
            }

            mMagic = buf.getInt();
            mNanoAppId = buf.getLong();
            mNanoAppVersion = buf.getInt();
            mFlags = buf.getInt();
            mHwHubType = buf.getLong();
            mTargetChreApiMajorVersion = buf.get();
            mTargetChreApiMinorVersion = buf.get();
        } catch (BufferUnderflowException e) {
            Log.e(TAG, "Not enough contents in nanoapp header");
            return;
        }

        if (mMagic != EXPECTED_MAGIC_VALUE) {
            Log.e(TAG, "Unexpected magic value " + String.format("0x%08X", mMagic)
                    + "while parsing header (expected "
                    + String.format("0x%08X", EXPECTED_MAGIC_VALUE) + ")");
        } else {
            mHasValidHeader = true;
        }
    }

    /**
     * @return the app binary byte array
     */
    public byte[] getBinary() {
        return mNanoAppBinary;
    }

    /**
     * @return the app binary byte array without the leading header
     *
     * @throws IndexOutOfBoundsException if the nanoapp binary size is smaller than the header size
     * @throws NullPointerException if the nanoapp binary is null
     */
    public byte[] getBinaryNoHeader() {
        if (mNanoAppBinary.length < HEADER_SIZE_BYTES) {
            throw new IndexOutOfBoundsException("NanoAppBinary binary byte size ("
                + mNanoAppBinary.length + ") is less than header size (" + HEADER_SIZE_BYTES + ")");
        }

        return Arrays.copyOfRange(mNanoAppBinary, HEADER_SIZE_BYTES, mNanoAppBinary.length);
    }

    /**
     * @return {@code true} if the header is valid, {@code false} otherwise
     */
    public boolean hasValidHeader() {
        return mHasValidHeader;
    }

    /**
     * @return the header version
     */
    public int getHeaderVersion() {
        return mHeaderVersion;
    }

    /**
     * @return the app ID parsed from the nanoapp header
     */
    public long getNanoAppId() {
        return mNanoAppId;
    }

    /**
     * @return the app version parsed from the nanoapp header
     */
    public int getNanoAppVersion() {
        return mNanoAppVersion;
    }

    /**
     * @return the compile target hub type parsed from the nanoapp header
     */
    public long getHwHubType() {
        return mHwHubType;
    }

    /**
     * @return the target CHRE API major version parsed from the nanoapp header
     */
    public byte getTargetChreApiMajorVersion() {
        return mTargetChreApiMajorVersion;
    }

    /**
     * @return the target CHRE API minor version parsed from the nanoapp header
     */
    public byte getTargetChreApiMinorVersion() {
        return mTargetChreApiMinorVersion;
    }

    /**
     * Returns the flags for the nanoapp as defined in context_hub.h.
     *
     * This method is meant to be used by the Context Hub Service.
     *
     * @return the flags for the nanoapp
     */
    public int getFlags() {
        return mFlags;
    }

    /**
     * @return {@code true} if the nanoapp binary is signed, {@code false} otherwise
     */
    public boolean isSigned() {
        return (mFlags & NANOAPP_SIGNED_FLAG_BIT) != 0;
    }

    /**
     * @return {@code true} if the nanoapp binary is encrypted, {@code false} otherwise
     */
    public boolean isEncrypted() {
        return (mFlags & NANOAPP_ENCRYPTED_FLAG_BIT) != 0;
    }

    private NanoAppBinary(Parcel in) {
        int binaryLength = in.readInt();
        mNanoAppBinary = new byte[binaryLength];
        in.readByteArray(mNanoAppBinary);

        parseBinaryHeader();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mNanoAppBinary.length);
        out.writeByteArray(mNanoAppBinary);
    }

    public static final @android.annotation.NonNull Creator<NanoAppBinary> CREATOR =
            new Creator<NanoAppBinary>() {
                @Override
                public NanoAppBinary createFromParcel(Parcel in) {
                    return new NanoAppBinary(in);
                }

                @Override
                public NanoAppBinary[] newArray(int size) {
                    return new NanoAppBinary[size];
                }
            };
}
