/*
 * Copyright (C) 2015 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.
 */

#define LOG_TAG "PersistableBundle"

#include <binder/PersistableBundle.h>

#include <limits>

#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/Errors.h>

using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::sp;
using android::status_t;
using android::UNEXPECTED_NULL;

enum {
    // Keep in sync with BUNDLE_MAGIC in frameworks/base/core/java/android/os/BaseBundle.java.
    BUNDLE_MAGIC = 0x4C444E42,
};

enum {
    // Keep in sync with frameworks/base/core/java/android/os/Parcel.java.
    VAL_STRING = 0,
    VAL_INTEGER = 1,
    VAL_LONG = 6,
    VAL_DOUBLE = 8,
    VAL_BOOLEAN = 9,
    VAL_STRINGARRAY = 14,
    VAL_INTARRAY = 18,
    VAL_LONGARRAY = 19,
    VAL_BOOLEANARRAY = 23,
    VAL_PERSISTABLEBUNDLE = 25,
    VAL_DOUBLEARRAY = 28,
};

namespace {
template <typename T>
bool getValue(const android::String16& key, T* out, const std::map<android::String16, T>& map) {
    const auto& it = map.find(key);
    if (it == map.end()) return false;
    *out = it->second;
    return true;
}
}  // namespace

namespace android {

namespace os {

#define RETURN_IF_FAILED(calledOnce)                                     \
    {                                                                    \
        status_t returnStatus = calledOnce;                              \
        if (returnStatus) {                                              \
            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
            return returnStatus;                                         \
         }                                                               \
    }

#define RETURN_IF_ENTRY_ERASED(map, key)                                 \
    {                                                                    \
        size_t num_erased = map.erase(key);                              \
        if (num_erased) {                                                \
            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
            return num_erased;                                           \
         }                                                               \
    }

status_t PersistableBundle::writeToParcel(Parcel* parcel) const {
    /*
     * Keep implementation in sync with writeToParcelInner() in
     * frameworks/base/core/java/android/os/BaseBundle.java.
     */

    // Special case for empty bundles.
    if (empty()) {
        RETURN_IF_FAILED(parcel->writeInt32(0));
        return NO_ERROR;
    }

    size_t length_pos = parcel->dataPosition();
    RETURN_IF_FAILED(parcel->writeInt32(1));  // dummy, will hold length
    RETURN_IF_FAILED(parcel->writeInt32(BUNDLE_MAGIC));

    size_t start_pos = parcel->dataPosition();
    RETURN_IF_FAILED(writeToParcelInner(parcel));
    size_t end_pos = parcel->dataPosition();

    // Backpatch length. This length value includes the length header.
    parcel->setDataPosition(length_pos);
    size_t length = end_pos - start_pos;
    if (length > std::numeric_limits<int32_t>::max()) {
        ALOGE("Parcel length (%zu) too large to store in 32-bit signed int", length);
        return BAD_VALUE;
    }
    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(length)));
    parcel->setDataPosition(end_pos);
    return NO_ERROR;
}

status_t PersistableBundle::readFromParcel(const Parcel* parcel) {
    /*
     * Keep implementation in sync with readFromParcelInner() in
     * frameworks/base/core/java/android/os/BaseBundle.java.
     */
    int32_t length = parcel->readInt32();
    if (length < 0) {
        ALOGE("Bad length in parcel: %d", length);
        return UNEXPECTED_NULL;
    }

    return readFromParcelInner(parcel, static_cast<size_t>(length));
}

bool PersistableBundle::empty() const {
    return size() == 0u;
}

size_t PersistableBundle::size() const {
    return (mBoolMap.size() +
            mIntMap.size() +
            mLongMap.size() +
            mDoubleMap.size() +
            mStringMap.size() +
            mBoolVectorMap.size() +
            mIntVectorMap.size() +
            mLongVectorMap.size() +
            mDoubleVectorMap.size() +
            mStringVectorMap.size() +
            mPersistableBundleMap.size());
}

size_t PersistableBundle::erase(const String16& key) {
    RETURN_IF_ENTRY_ERASED(mBoolMap, key);
    RETURN_IF_ENTRY_ERASED(mIntMap, key);
    RETURN_IF_ENTRY_ERASED(mLongMap, key);
    RETURN_IF_ENTRY_ERASED(mDoubleMap, key);
    RETURN_IF_ENTRY_ERASED(mStringMap, key);
    RETURN_IF_ENTRY_ERASED(mBoolVectorMap, key);
    RETURN_IF_ENTRY_ERASED(mIntVectorMap, key);
    RETURN_IF_ENTRY_ERASED(mLongVectorMap, key);
    RETURN_IF_ENTRY_ERASED(mDoubleVectorMap, key);
    RETURN_IF_ENTRY_ERASED(mStringVectorMap, key);
    return mPersistableBundleMap.erase(key);
}

void PersistableBundle::putBoolean(const String16& key, bool value) {
    erase(key);
    mBoolMap[key] = value;
}

void PersistableBundle::putInt(const String16& key, int32_t value) {
    erase(key);
    mIntMap[key] = value;
}

void PersistableBundle::putLong(const String16& key, int64_t value) {
    erase(key);
    mLongMap[key] = value;
}

void PersistableBundle::putDouble(const String16& key, double value) {
    erase(key);
    mDoubleMap[key] = value;
}

void PersistableBundle::putString(const String16& key, const String16& value) {
    erase(key);
    mStringMap[key] = value;
}

void PersistableBundle::putBooleanVector(const String16& key, const std::vector<bool>& value) {
    erase(key);
    mBoolVectorMap[key] = value;
}

void PersistableBundle::putIntVector(const String16& key, const std::vector<int32_t>& value) {
    erase(key);
    mIntVectorMap[key] = value;
}

void PersistableBundle::putLongVector(const String16& key, const std::vector<int64_t>& value) {
    erase(key);
    mLongVectorMap[key] = value;
}

void PersistableBundle::putDoubleVector(const String16& key, const std::vector<double>& value) {
    erase(key);
    mDoubleVectorMap[key] = value;
}

void PersistableBundle::putStringVector(const String16& key, const std::vector<String16>& value) {
    erase(key);
    mStringVectorMap[key] = value;
}

void PersistableBundle::putPersistableBundle(const String16& key, const PersistableBundle& value) {
    erase(key);
    mPersistableBundleMap[key] = value;
}

bool PersistableBundle::getBoolean(const String16& key, bool* out) const {
    return getValue(key, out, mBoolMap);
}

bool PersistableBundle::getInt(const String16& key, int32_t* out) const {
    return getValue(key, out, mIntMap);
}

bool PersistableBundle::getLong(const String16& key, int64_t* out) const {
    return getValue(key, out, mLongMap);
}

bool PersistableBundle::getDouble(const String16& key, double* out) const {
    return getValue(key, out, mDoubleMap);
}

bool PersistableBundle::getString(const String16& key, String16* out) const {
    return getValue(key, out, mStringMap);
}

bool PersistableBundle::getBooleanVector(const String16& key, std::vector<bool>* out) const {
    return getValue(key, out, mBoolVectorMap);
}

bool PersistableBundle::getIntVector(const String16& key, std::vector<int32_t>* out) const {
    return getValue(key, out, mIntVectorMap);
}

bool PersistableBundle::getLongVector(const String16& key, std::vector<int64_t>* out) const {
    return getValue(key, out, mLongVectorMap);
}

bool PersistableBundle::getDoubleVector(const String16& key, std::vector<double>* out) const {
    return getValue(key, out, mDoubleVectorMap);
}

bool PersistableBundle::getStringVector(const String16& key, std::vector<String16>* out) const {
    return getValue(key, out, mStringVectorMap);
}

bool PersistableBundle::getPersistableBundle(const String16& key, PersistableBundle* out) const {
    return getValue(key, out, mPersistableBundleMap);
}

status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const {
    /*
     * To keep this implementation in sync with writeArrayMapInternal() in
     * frameworks/base/core/java/android/os/Parcel.java, the number of key
     * value pairs must be written into the parcel before writing the key-value
     * pairs themselves.
     */
    size_t num_entries = size();
    if (num_entries > std::numeric_limits<int32_t>::max()) {
        ALOGE("The size of this PersistableBundle (%zu) too large to store in 32-bit signed int",
              num_entries);
        return BAD_VALUE;
    }
    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(num_entries)));

    for (const auto& key_val_pair : mBoolMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEAN));
        RETURN_IF_FAILED(parcel->writeBool(key_val_pair.second));
    }
    for (const auto& key_val_pair : mIntMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_INTEGER));
        RETURN_IF_FAILED(parcel->writeInt32(key_val_pair.second));
    }
    for (const auto& key_val_pair : mLongMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_LONG));
        RETURN_IF_FAILED(parcel->writeInt64(key_val_pair.second));
    }
    for (const auto& key_val_pair : mDoubleMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLE));
        RETURN_IF_FAILED(parcel->writeDouble(key_val_pair.second));
    }
    for (const auto& key_val_pair : mStringMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_STRING));
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.second));
    }
    for (const auto& key_val_pair : mBoolVectorMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEANARRAY));
        RETURN_IF_FAILED(parcel->writeBoolVector(key_val_pair.second));
    }
    for (const auto& key_val_pair : mIntVectorMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_INTARRAY));
        RETURN_IF_FAILED(parcel->writeInt32Vector(key_val_pair.second));
    }
    for (const auto& key_val_pair : mLongVectorMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_LONGARRAY));
        RETURN_IF_FAILED(parcel->writeInt64Vector(key_val_pair.second));
    }
    for (const auto& key_val_pair : mDoubleVectorMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLEARRAY));
        RETURN_IF_FAILED(parcel->writeDoubleVector(key_val_pair.second));
    }
    for (const auto& key_val_pair : mStringVectorMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_STRINGARRAY));
        RETURN_IF_FAILED(parcel->writeString16Vector(key_val_pair.second));
    }
    for (const auto& key_val_pair : mPersistableBundleMap) {
        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
        RETURN_IF_FAILED(parcel->writeInt32(VAL_PERSISTABLEBUNDLE));
        RETURN_IF_FAILED(key_val_pair.second.writeToParcel(parcel));
    }
    return NO_ERROR;
}

status_t PersistableBundle::readFromParcelInner(const Parcel* parcel, size_t length) {
    /*
     * Note: we don't actually use length for anything other than an empty PersistableBundle
     * check, since we do not actually need to copy in an entire Parcel, unlike in the Java
     * implementation.
     */
    if (length == 0) {
        // Empty PersistableBundle or end of data.
        return NO_ERROR;
    }

    int32_t magic;
    RETURN_IF_FAILED(parcel->readInt32(&magic));
    if (magic != BUNDLE_MAGIC) {
        ALOGE("Bad magic number for PersistableBundle: 0x%08x", magic);
        return BAD_VALUE;
    }

    /*
     * To keep this implementation in sync with unparcel() in
     * frameworks/base/core/java/android/os/BaseBundle.java, the number of
     * key-value pairs must be read from the parcel before reading the key-value
     * pairs themselves.
     */
    int32_t num_entries;
    RETURN_IF_FAILED(parcel->readInt32(&num_entries));

    for (; num_entries > 0; --num_entries) {
        size_t start_pos = parcel->dataPosition();
        String16 key;
        int32_t value_type;
        RETURN_IF_FAILED(parcel->readString16(&key));
        RETURN_IF_FAILED(parcel->readInt32(&value_type));

        /*
         * We assume that both the C++ and Java APIs ensure that all keys in a PersistableBundle
         * are unique.
         */
        switch (value_type) {
            case VAL_STRING: {
                RETURN_IF_FAILED(parcel->readString16(&mStringMap[key]));
                break;
            }
            case VAL_INTEGER: {
                RETURN_IF_FAILED(parcel->readInt32(&mIntMap[key]));
                break;
            }
            case VAL_LONG: {
                RETURN_IF_FAILED(parcel->readInt64(&mLongMap[key]));
                break;
            }
            case VAL_DOUBLE: {
                RETURN_IF_FAILED(parcel->readDouble(&mDoubleMap[key]));
                break;
            }
            case VAL_BOOLEAN: {
                RETURN_IF_FAILED(parcel->readBool(&mBoolMap[key]));
                break;
            }
            case VAL_STRINGARRAY: {
                RETURN_IF_FAILED(parcel->readString16Vector(&mStringVectorMap[key]));
                break;
            }
            case VAL_INTARRAY: {
                RETURN_IF_FAILED(parcel->readInt32Vector(&mIntVectorMap[key]));
                break;
            }
            case VAL_LONGARRAY: {
                RETURN_IF_FAILED(parcel->readInt64Vector(&mLongVectorMap[key]));
                break;
            }
            case VAL_BOOLEANARRAY: {
                RETURN_IF_FAILED(parcel->readBoolVector(&mBoolVectorMap[key]));
                break;
            }
            case VAL_PERSISTABLEBUNDLE: {
                RETURN_IF_FAILED(mPersistableBundleMap[key].readFromParcel(parcel));
                break;
            }
            case VAL_DOUBLEARRAY: {
                RETURN_IF_FAILED(parcel->readDoubleVector(&mDoubleVectorMap[key]));
                break;
            }
            default: {
                ALOGE("Unrecognized type: %d", value_type);
                return BAD_TYPE;
                break;
            }
        }
    }

    return NO_ERROR;
}

}  // namespace os

}  // namespace android
