/*
 * Copyright (C) 2016 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.util;

import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.Process;
import libcore.io.IoUtils;

import java.io.Closeable;
import java.io.IOException;
import java.util.UUID;

/**
 * This class is an array of integers that is backed by shared memory.
 * It is useful for efficiently sharing state between processes. The
 * write and read operations are guaranteed to not result in read/
 * write memory tear, i.e. they are atomic. However, multiple read/
 * write operations are <strong>not</strong> synchronized between
 * each other.
 * <p>
 * The data structure is designed to have one owner process that can
 * read/write. There may be multiple client processes that can only read.
 * The owner process is the process that created the array. The shared
 * memory is pinned (not reclaimed by the system) until the owning process
 * dies or the data structure is closed. This class is <strong>not</strong>
 * thread safe. You should not interact with an instance of this class
 * once it is closed. If you pass back to the owner process an instance
 * it will be read only even in the owning process.
 * </p>
 *
 * @hide
 */
public final class MemoryIntArray implements Parcelable, Closeable {
    private static final String TAG = "MemoryIntArray";

    private static final int MAX_SIZE = 1024;

    private final boolean mIsOwner;
    private final long mMemoryAddr;
    private int mFd;

    /**
     * Creates a new instance.
     *
     * @param size The size of the array in terms of integer slots. Cannot be
     *     more than {@link #getMaxSize()}.
     * @param clientWritable Whether other processes can write to the array.
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    public MemoryIntArray(int size) throws IOException {
        if (size > MAX_SIZE) {
            throw new IllegalArgumentException("Max size is " + MAX_SIZE);
        }
        mIsOwner = true;
        final String name = UUID.randomUUID().toString();
        mFd = nativeCreate(name, size);
        mMemoryAddr = nativeOpen(mFd, mIsOwner);
    }

    private MemoryIntArray(Parcel parcel) throws IOException {
        mIsOwner = false;
        ParcelFileDescriptor pfd = parcel.readParcelable(null);
        if (pfd == null) {
            throw new IOException("No backing file descriptor");
        }
        mFd = pfd.detachFd();
        mMemoryAddr = nativeOpen(mFd, mIsOwner);
    }

    /**
     * @return Gets whether this array is mutable.
     */
    public boolean isWritable() {
        enforceNotClosed();
        return mIsOwner;
    }

    /**
     * Gets the value at a given index.
     *
     * @param index The index.
     * @return The value at this index.
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    public int get(int index) throws IOException {
        enforceNotClosed();
        enforceValidIndex(index);
        return nativeGet(mFd, mMemoryAddr, index);
    }

    /**
     * Sets the value at a given index. This method can be called only if
     * {@link #isWritable()} returns true which means your process is the
     * owner.
     *
     * @param index The index.
     * @param value The value to set.
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    public void set(int index, int value) throws IOException {
        enforceNotClosed();
        enforceWritable();
        enforceValidIndex(index);
        nativeSet(mFd, mMemoryAddr, index, value);
    }

    /**
     * Gets the array size.
     *
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    public int size() throws IOException {
        enforceNotClosed();
        return nativeSize(mFd);
    }

    /**
     * Closes the array releasing resources.
     *
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    @Override
    public void close() throws IOException {
        if (!isClosed()) {
            nativeClose(mFd, mMemoryAddr, mIsOwner);
            mFd = -1;
        }
    }

    /**
     * @return Whether this array is closed and shouldn't be used.
     */
    public boolean isClosed() {
        return mFd == -1;
    }

    @Override
    protected void finalize() throws Throwable {
        IoUtils.closeQuietly(this);
        super.finalize();
    }

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

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
        try {
            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } finally {
            pfd.detachFd();
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        MemoryIntArray other = (MemoryIntArray) obj;
        return mFd == other.mFd;
    }

    @Override
    public int hashCode() {
        return mFd;
    }

    private void enforceNotClosed() {
        if (isClosed()) {
            throw new IllegalStateException("cannot interact with a closed instance");
        }
    }

    private void enforceValidIndex(int index) throws IOException {
        final int size = size();
        if (index < 0 || index > size - 1) {
            throw new IndexOutOfBoundsException(
                    index + " not between 0 and " + (size - 1));
        }
    }

    private void enforceWritable() {
        if (!isWritable()) {
            throw new UnsupportedOperationException("array is not writable");
        }
    }

    private native int nativeCreate(String name, int size);
    private native long nativeOpen(int fd, boolean owner);
    private native void nativeClose(int fd, long memoryAddr, boolean owner);
    private native int nativeGet(int fd, long memoryAddr, int index);
    private native void nativeSet(int fd, long memoryAddr, int index, int value);
    private native int nativeSize(int fd);

    /**
     * @return The max array size.
     */
    public static int getMaxSize() {
        return MAX_SIZE;
    }

    public static final Parcelable.Creator<MemoryIntArray> CREATOR =
            new Parcelable.Creator<MemoryIntArray>() {
        @Override
        public MemoryIntArray createFromParcel(Parcel parcel) {
            try {
                return new MemoryIntArray(parcel);
            } catch (IOException ioe) {
                throw new IllegalArgumentException("Error unparceling MemoryIntArray");
            }
        }

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