use libjsoncpp instead of android::JSONObject

Bug: 141887532
Test: locally
Change-Id: I2c07e0d8cfa19b70d81d010bcdc1546587a964bd
diff --git a/host/frontend/gcastv2/libandroid/Android.bp b/host/frontend/gcastv2/libandroid/Android.bp
index a507d09..2c91a04 100644
--- a/host/frontend/gcastv2/libandroid/Android.bp
+++ b/host/frontend/gcastv2/libandroid/Android.bp
@@ -25,7 +25,6 @@
         "AnotherPacketSource.cpp",
         "ATSParser.cpp",
         "ESQueue.cpp",
-        "JSONObject.cpp",
         "NuMediaExtractor.cpp",
         "Utils.cpp",
         "avc_utils.cpp",
diff --git a/host/frontend/gcastv2/libandroid/JSONObject.cpp b/host/frontend/gcastv2/libandroid/JSONObject.cpp
deleted file mode 100644
index 0ece325..0000000
--- a/host/frontend/gcastv2/libandroid/JSONObject.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * Copyright (C) 2013 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_NDEBUG 0
-#define LOG_TAG "JSONObject"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/JSONObject.h>
-
-#include <ctype.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-namespace {
-    const char kIndent[] = "                                        ";
-}
-
-// static
-ssize_t JSONValue::Parse(const char *data, size_t size, JSONValue *out) {
-    size_t offset = 0;
-    while (offset < size && isspace(data[offset])) {
-        ++offset;
-    }
-
-    if (offset == size) {
-        return ERROR_MALFORMED;
-    }
-
-    if (data[offset] == '[') {
-        std::shared_ptr<JSONArray> array(new JSONArray);
-        ++offset;
-
-        for (;;) {
-            while (offset < size && isspace(data[offset])) {
-                ++offset;
-            }
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-
-            if (data[offset] == ']') {
-                ++offset;
-                break;
-            }
-
-            JSONValue val;
-            ssize_t n = Parse(&data[offset], size - offset, &val);
-
-            if (n < 0) {
-                return n;
-            }
-
-            array->addValue(val);
-
-            offset += n;
-
-            while (offset < size && isspace(data[offset])) {
-                ++offset;
-            }
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-
-            if (data[offset] == ',') {
-                ++offset;
-            } else if (data[offset] != ']') {
-                return ERROR_MALFORMED;
-            }
-        };
-
-        out->setArray(array);
-
-        return offset;
-    } else if (data[offset] == '{') {
-        std::shared_ptr<JSONObject> obj(new JSONObject);
-        ++offset;
-
-        for (;;) {
-            while (offset < size && isspace(data[offset])) {
-                ++offset;
-            }
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-
-            if (data[offset] == '}') {
-                ++offset;
-                break;
-            }
-
-            JSONValue key;
-            ssize_t n = Parse(&data[offset], size - offset, &key);
-
-            if (n < 0) {
-                return n;
-            }
-
-            if (key.type() != TYPE_STRING) {
-                return ERROR_MALFORMED;
-            }
-
-            offset += n;
-
-            while (offset < size && isspace(data[offset])) {
-                ++offset;
-            }
-
-            if (offset == size || data[offset] != ':') {
-                return ERROR_MALFORMED;
-            }
-
-            ++offset;
-
-            JSONValue val;
-            n = Parse(&data[offset], size - offset, &val);
-
-            if (n < 0) {
-                return n;
-            }
-
-            std::string keyVal;
-            CHECK(key.getString(&keyVal));
-
-            obj->setValue(keyVal.c_str(), val);
-
-            offset += n;
-
-            while (offset < size && isspace(data[offset])) {
-                ++offset;
-            }
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-
-            if (data[offset] == ',') {
-                ++offset;
-            } else if (data[offset] != '}') {
-                return ERROR_MALFORMED;
-            }
-        };
-
-        out->setObject(obj);
-
-        return offset;
-    } else if (data[offset] == '"') {
-        ++offset;
-
-        std::string s;
-        bool escaped = false;
-        while (offset < size) {
-            if (escaped) {
-                char c;
-                switch (data[offset]) {
-                    case '\"':
-                    case '\\':
-                    case '/':
-                        c = data[offset];
-                        break;
-                    case 'b':
-                        c = '\x08';
-                        break;
-                    case 'f':
-                        c = '\x0c';
-                        break;
-                    case 'n':
-                        c = '\x0a';
-                        break;
-                    case 'r':
-                        c = '\x0d';
-                        break;
-                    case 't':
-                        c = '\x09';
-                        break;
-                    default:
-                        return ERROR_MALFORMED;
-                }
-
-                s.append(1, c);
-                ++offset;
-
-                escaped = false;
-                continue;
-            } else if (data[offset] == '\\') {
-                escaped = true;
-                ++offset;
-                continue;
-            } else if (data[offset] == '"') {
-                break;
-            }
-
-            s.append(1, data[offset++]);
-        }
-
-        if (offset == size) {
-            return ERROR_MALFORMED;
-        }
-
-        ++offset;
-        out->setString(s);
-
-        return offset;
-    } else if (isdigit(data[offset]) || data[offset] == '-') {
-        bool negate = false;
-        if (data[offset] == '-') {
-            negate = true;
-            ++offset;
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-        }
-
-        size_t firstDigitOffset = offset;
-        while (offset < size && isdigit(data[offset])) {
-            ++offset;
-        }
-
-        size_t numDigits = offset - firstDigitOffset;
-        if (numDigits > 1 && data[firstDigitOffset] == '0') {
-            // No leading zeros.
-            return ERROR_MALFORMED;
-        }
-
-        size_t firstFracDigitOffset = 0;
-        size_t numFracDigits = 0;
-
-        if (offset < size && data[offset] == '.') {
-            ++offset;
-
-            firstFracDigitOffset = offset;
-            while (offset < size && isdigit(data[offset])) {
-                ++offset;
-            }
-
-            numFracDigits = offset - firstFracDigitOffset;
-            if (numFracDigits == 0) {
-                return ERROR_MALFORMED;
-            }
-        }
-
-        bool negateExponent = false;
-        size_t firstExpDigitOffset = 0;
-        size_t numExpDigits = 0;
-
-        if (offset < size && (data[offset] == 'e' || data[offset] == 'E')) {
-            ++offset;
-
-            if (offset == size) {
-                return ERROR_MALFORMED;
-            }
-
-            if (data[offset] == '+' || data[offset] == '-') {
-                if (data[offset] == '-') {
-                    negateExponent = true;
-                }
-
-                ++offset;
-            }
-
-            firstExpDigitOffset = offset;
-            while (offset < size && isdigit(data[offset])) {
-                ++offset;
-            }
-
-            numExpDigits = offset - firstExpDigitOffset;
-            if (numExpDigits == 0) {
-                return ERROR_MALFORMED;
-            }
-        }
-
-        CHECK_EQ(numFracDigits, 0u);
-        CHECK_EQ(numExpDigits, 0u);
-
-        int32_t x = 0;
-        for (size_t i = 0; i < numDigits; ++i) {
-            x *= 10;
-            x += data[firstDigitOffset + i] - '0';
-
-            CHECK_GE(x, 0);
-        }
-
-        if (negate) {
-            x = -x;
-        }
-
-        out->setInt32(x);
-
-        return offset;
-    } else if (offset + 4 <= size && !strncmp("null", &data[offset], 4)) {
-        out->unset();
-        return offset + 4;
-    } else if (offset + 4 <= size && !strncmp("true", &data[offset], 4)) {
-        out->setBoolean(true);
-        return offset + 4;
-    } else if (offset + 5 <= size && !strncmp("false", &data[offset], 5)) {
-        out->setBoolean(false);
-        return offset + 5;
-    }
-
-    return ERROR_MALFORMED;
-}
-
-JSONValue::JSONValue()
-    : mType(TYPE_NULL) {
-}
-
-JSONValue::JSONValue(const JSONValue &other)
-    : mType(TYPE_NULL) {
-    *this = other;
-}
-
-JSONValue &JSONValue::operator=(const JSONValue &other) {
-    if (&other != this) {
-        unset();
-        mType = other.mType;
-        mValue = other.mValue;
-        mObjectOrArray = other.mObjectOrArray;
-
-        switch (mType) {
-            case TYPE_STRING:
-                mValue.mString = new std::string(*other.mValue.mString);
-                break;
-            case TYPE_OBJECT:
-            case TYPE_ARRAY:
-            default:
-                break;
-        }
-    }
-
-    return *this;
-}
-
-JSONValue::~JSONValue() {
-    unset();
-}
-
-JSONValue::FieldType JSONValue::type() const {
-    return mType;
-}
-
-bool JSONValue::getInt32(int32_t *value) const {
-    if (mType != TYPE_NUMBER) {
-        return false;
-    }
-
-    *value = mValue.mInt32;
-    return true;
-}
-
-bool JSONValue::getString(std::string *value) const {
-    if (mType != TYPE_STRING) {
-        return false;
-    }
-
-    *value = *mValue.mString;
-    return true;
-}
-
-bool JSONValue::getBoolean(bool *value) const {
-    if (mType != TYPE_BOOLEAN) {
-        return false;
-    }
-
-    *value = mValue.mBoolean;
-    return true;
-}
-
-bool JSONValue::getObject(std::shared_ptr<JSONObject> *value) const {
-    if (mType != TYPE_OBJECT) {
-        return false;
-    }
-
-    *value = std::static_pointer_cast<JSONObject>(mObjectOrArray);
-    return true;
-}
-
-bool JSONValue::getArray(std::shared_ptr<JSONArray> *value) const {
-    if (mType != TYPE_ARRAY) {
-        return false;
-    }
-
-    *value = std::static_pointer_cast<JSONArray>(mObjectOrArray);
-    return true;
-}
-
-void JSONValue::setInt32(int32_t value) {
-    unset();
-
-    mValue.mInt32 = value;
-    mType = TYPE_NUMBER;
-}
-
-void JSONValue::setString(std::string_view value) {
-    unset();
-
-    mValue.mString = new std::string(value);
-    mType = TYPE_STRING;
-}
-
-void JSONValue::setBoolean(bool value) {
-    unset();
-
-    mValue.mBoolean = value;
-    mType = TYPE_BOOLEAN;
-}
-
-void JSONValue::setObject(std::shared_ptr<JSONObject> obj) {
-    unset();
-
-    mObjectOrArray = obj;
-
-    mType = TYPE_OBJECT;
-}
-
-void JSONValue::setArray(std::shared_ptr<JSONArray> array) {
-    unset();
-
-    mObjectOrArray = array;
-
-    mType = TYPE_ARRAY;
-}
-
-void JSONValue::unset() {
-    switch (mType) {
-        case TYPE_STRING:
-            delete mValue.mString;
-            break;
-        case TYPE_OBJECT:
-        case TYPE_ARRAY:
-            mObjectOrArray.reset();
-            break;
-
-        default:
-            break;
-    }
-
-    mType = TYPE_NULL;
-}
-
-static void EscapeString(const char *in, size_t inSize, std::string *out) {
-    CHECK(in != out->c_str());
-    out->clear();
-
-    for (size_t i = 0; i < inSize; ++i) {
-        char c = in[i];
-        switch (c) {
-            case '\"':
-                out->append("\\\"");
-                break;
-            case '\\':
-                out->append("\\\\");
-                break;
-            case '/':
-                out->append("\\/");
-                break;
-            case '\x08':
-                out->append("\\b");
-                break;
-            case '\x0c':
-                out->append("\\f");
-                break;
-            case '\x0a':
-                out->append("\\n");
-                break;
-            case '\x0d':
-                out->append("\\r");
-                break;
-            case '\x09':
-                out->append("\\t");
-                break;
-            default:
-                out->append(1, c);
-                break;
-        }
-    }
-}
-
-std::string JSONValue::toString(size_t depth, bool indentFirstLine) const {
-
-    std::string out;
-
-    switch (mType) {
-        case TYPE_STRING:
-        {
-            std::string escaped;
-            EscapeString(
-                    mValue.mString->c_str(), mValue.mString->size(), &escaped);
-
-            out.append("\"");
-            out.append(escaped);
-            out.append("\"");
-            break;
-        }
-
-        case TYPE_NUMBER:
-        {
-            out = StringPrintf("%d", mValue.mInt32);
-            break;
-        }
-
-        case TYPE_BOOLEAN:
-        {
-            out = mValue.mBoolean ? "true" : "false";
-            break;
-        }
-
-        case TYPE_NULL:
-        {
-            out = "null";
-            break;
-        }
-
-        case TYPE_OBJECT:
-        case TYPE_ARRAY:
-        {
-            out = (mType == TYPE_OBJECT) ? "{\n" : "[\n";
-            out.append(mObjectOrArray->internalToString(depth + 1, true));
-            out.append("\n");
-            out.append(kIndent, 2 * depth);
-            out.append(mType == TYPE_OBJECT ? "}" : "]");
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-
-    if (indentFirstLine) {
-        out.insert(0, kIndent, 2 * depth);
-    }
-
-    return out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-// static
-std::shared_ptr<JSONCompound> JSONCompound::Parse(const char *data, size_t size) {
-    JSONValue value;
-    ssize_t result = JSONValue::Parse(data, size, &value);
-
-    if (result < 0) {
-        return NULL;
-    }
-
-    std::shared_ptr<JSONObject> obj;
-    if (value.getObject(&obj)) {
-        return obj;
-    }
-
-    std::shared_ptr<JSONArray> array;
-    if (value.getArray(&array)) {
-        return array;
-    }
-
-    return NULL;
-}
-
-std::string JSONCompound::toString(size_t depth, bool indentFirstLine) const {
-    std::string out;
-
-    if (indentFirstLine) {
-        out.insert(0, kIndent, 2 * depth);
-    }
-    
-    out = isObject() ? "{\n" : "[\n";
-    out.append(internalToString(depth + 1, true));
-    out.append("\n");
-    out.append(kIndent, 2 * depth);
-    out.append(isObject() ? "}" : "]");
-
-    return out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-JSONObject::JSONObject() {}
-JSONObject::~JSONObject() {}
-
-bool JSONObject::isObject() const {
-    return true;
-}
-
-bool JSONObject::getValue(const char *key, JSONValue *value) const {
-    auto it = mValues.find(key);
-
-    if (it == mValues.end()) {
-        return false;
-    }
-
-    *value = it->second;
-
-    return true;
-}
-
-void JSONObject::setValue(const char *key, const JSONValue &value) {
-    mValues[std::string(key)] = value;
-}
-
-void JSONObject::remove(const char *key) {
-    mValues.erase(key);
-}
-
-std::string JSONObject::internalToString(
-        size_t depth, bool /* indentFirstLine */) const {
-    std::string out;
-    for (auto it = mValues.begin(); it != mValues.end();) {
-        const std::string &key = it->first;
-        std::string escapedKey;
-        EscapeString(key.c_str(), key.size(), &escapedKey);
-
-        out.append(kIndent, 2 * depth);
-        out.append("\"");
-        out.append(escapedKey);
-        out.append("\": ");
-
-        out.append(it->second.toString(depth + 1, false));
-
-        ++it;
-        if (it != mValues.end()) {
-            out.append(",\n");
-        }
-    }
-
-    return out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-JSONArray::JSONArray() {}
-
-JSONArray::~JSONArray() {}
-
-bool JSONArray::isObject() const {
-    return false;
-}
-
-size_t JSONArray::size() const {
-    return mValues.size();
-}
-
-bool JSONArray::getValue(size_t key, JSONValue *value) const {
-    if (key >= mValues.size()) {
-        return false;
-    }
-
-    *value = mValues[key];
-
-    return true;
-}
-
-void JSONArray::addValue(const JSONValue &value) {
-    mValues.push_back(value);
-}
-
-std::string JSONArray::internalToString(
-        size_t depth, bool /* indentFirstLine */) const {
-    std::string out;
-    for (size_t i = 0; i < mValues.size(); ++i) {
-        out.append(mValues[i].toString(depth));
-
-        if (i + 1 < mValues.size()) {
-            out.append(",\n");
-        }
-    }
-
-    return out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-}  // namespace android
-
diff --git a/host/frontend/gcastv2/libandroid/include/media/stagefright/foundation/JSONObject.h b/host/frontend/gcastv2/libandroid/include/media/stagefright/foundation/JSONObject.h
deleted file mode 100644
index 41a1129..0000000
--- a/host/frontend/gcastv2/libandroid/include/media/stagefright/foundation/JSONObject.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef JSON_OBJECT_H_
-
-#define JSON_OBJECT_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/Errors.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <vector>
-
-namespace android {
-
-struct JSONArray;
-struct JSONCompound;
-struct JSONObject;
-
-struct JSONValue {
-    enum FieldType {
-        TYPE_STRING,
-        TYPE_NUMBER,
-        TYPE_BOOLEAN,
-        TYPE_NULL,
-        TYPE_OBJECT,
-        TYPE_ARRAY,
-    };
-
-    // Returns the number of bytes consumed or an error.
-    static ssize_t Parse(const char *data, size_t size, JSONValue *out);
-
-    JSONValue();
-    JSONValue(const JSONValue &);
-    JSONValue &operator=(const JSONValue &);
-    ~JSONValue();
-
-    FieldType type() const;
-    bool getInt32(int32_t *value) const;
-    bool getString(std::string *value) const;
-    bool getBoolean(bool *value) const;
-    bool getObject(std::shared_ptr<JSONObject> *value) const;
-    bool getArray(std::shared_ptr<JSONArray> *value) const;
-
-    void setInt32(int32_t value);
-    void setString(std::string_view value);
-    void setBoolean(bool value);
-    void setObject(std::shared_ptr<JSONObject> obj);
-    void setArray(std::shared_ptr<JSONArray> array);
-    void unset();  // i.e. setNull()
-
-    std::string toString(size_t depth = 0, bool indentFirstLine = true) const;
-
-private:
-    FieldType mType;
-
-    union {
-        int32_t mInt32;
-        std::string *mString;
-        bool mBoolean;
-    } mValue;
-    std::shared_ptr<JSONCompound> mObjectOrArray;
-};
-
-struct JSONCompound {
-    JSONCompound(const JSONCompound &) = delete;
-    JSONCompound &operator=(const JSONCompound &) = delete;
-
-    static std::shared_ptr<JSONCompound> Parse(const char *data, size_t size);
-
-    std::string toString(size_t depth = 0, bool indentFirstLine = true) const;
-
-    virtual bool isObject() const = 0;
-
-    virtual ~JSONCompound() {}
-
-protected:
-    virtual std::string internalToString(
-            size_t depth, bool indentFirstLine) const = 0;
-
-    JSONCompound() {}
-
-private:
-    friend struct JSONValue;
-};
-
-template<class KEY>
-struct JSONBase : public JSONCompound {
-    explicit JSONBase() {}
-
-    JSONBase(const JSONBase &) = delete;
-    JSONBase &operator=(const JSONBase &) = delete;
-
-#define PREAMBLE()                              \
-    JSONValue value;                            \
-    if (!getValue(key, &value)) {               \
-        return false;                           \
-    }
-
-    bool getFieldType(KEY key, JSONValue::FieldType *type) const {
-        PREAMBLE()
-        *type = value.type();
-        return true;
-    }
-
-    bool getInt32(KEY key, int32_t *out) const {
-        PREAMBLE()
-        return value.getInt32(out);
-    }
-
-    bool getString(KEY key, std::string *out) const {
-        PREAMBLE()
-        return value.getString(out);
-    }
-
-    bool getBoolean(KEY key, bool *out) const {
-        PREAMBLE()
-        return value.getBoolean(out);
-    }
-
-    bool getObject(KEY key, std::shared_ptr<JSONObject> *obj) const {
-        PREAMBLE()
-        return value.getObject(obj);
-    }
-
-    bool getArray(KEY key, std::shared_ptr<JSONArray> *obj) const {
-        PREAMBLE()
-        return value.getArray(obj);
-    }
-
-#undef PREAMBLE
-
-    virtual ~JSONBase() {}
-
-protected:
-    virtual bool getValue(KEY key, JSONValue *value) const = 0;
-};
-
-struct JSONObject : public JSONBase<const char *> {
-    explicit JSONObject();
-
-    JSONObject(const JSONObject &) = delete;
-    JSONObject &operator=(const JSONObject &) = delete;
-
-    virtual bool isObject() const;
-    void setValue(const char *key, const JSONValue &value);
-
-    void setInt32(const char *key, int32_t in) {
-        JSONValue val;
-        val.setInt32(in);
-        setValue(key, val);
-    }
-
-    void setString(const char *key, std::string_view in) {
-        JSONValue val;
-        val.setString(in);
-        setValue(key, val);
-    }
-
-    void setBoolean(const char *key, bool in) {
-        JSONValue val;
-        val.setBoolean(in);
-        setValue(key, val);
-    }
-
-    void setObject(const char *key, const std::shared_ptr<JSONObject> &obj) {
-        JSONValue val;
-        val.setObject(obj);
-        setValue(key, val);
-    }
-
-    void setArray(const char *key, const std::shared_ptr<JSONArray> &obj) {
-        JSONValue val;
-        val.setArray(obj);
-        setValue(key, val);
-    }
-
-    void remove(const char *key);
-
-    virtual ~JSONObject();
-
-protected:
-    virtual bool getValue(const char *key, JSONValue *value) const;
-    virtual std::string internalToString(size_t depth, bool indentFirstLine) const;
-
-private:
-    std::map<std::string, JSONValue> mValues;
-};
-
-struct JSONArray : public JSONBase<size_t> {
-    explicit JSONArray();
-
-    JSONArray(const JSONArray &) = delete;
-    JSONArray &operator=(const JSONArray &) = delete;
-
-    virtual bool isObject() const;
-    size_t size() const;
-    void addValue(const JSONValue &value);
-
-    void addInt32(int32_t in) {
-        JSONValue val;
-        val.setInt32(in);
-        addValue(val);
-    }
-
-    void addString(std::string_view in) {
-        JSONValue val;
-        val.setString(in);
-        addValue(val);
-    }
-
-    void addBoolean(bool in) {
-        JSONValue val;
-        val.setBoolean(in);
-        addValue(val);
-    }
-
-    void addObject(const std::shared_ptr<JSONObject> &obj) {
-        JSONValue val;
-        val.setObject(obj);
-        addValue(val);
-    }
-
-    void addArray(const std::shared_ptr<JSONArray> &obj) {
-        JSONValue val;
-        val.setArray(obj);
-        addValue(val);
-    }
-
-    virtual ~JSONArray();
-
-protected:
-    virtual bool getValue(size_t key, JSONValue *value) const;
-    virtual std::string internalToString(size_t depth, bool indentFirstLine) const;
-
-
-private:
-    std::vector<JSONValue> mValues;
-};
-
-}  // namespace android
-
-#endif  // JSON_OBJECT_H_
diff --git a/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp b/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp
index e526f61..0b79ca3 100644
--- a/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp
+++ b/host/frontend/gcastv2/webrtc/MyWebSocketHandler.cpp
@@ -4,14 +4,13 @@
 
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/foundation/JSONObject.h>
 #include <media/stagefright/Utils.h>
 
+#include <json/json.h>
+
 #include <netdb.h>
 #include <openssl/rand.h>
 
-using android::JSONValue;
-using android::JSONObject;
 using android::ABuffer;
 
 MyWebSocketHandler::MyWebSocketHandler(
@@ -37,35 +36,31 @@
         uint8_t /* headerByte */, const uint8_t *msg, size_t len) {
     // android::hexdump(msg, len);
 
-    JSONValue json;
-    if (JSONValue::Parse(
-                reinterpret_cast<const char *>(msg), len, &json) < 0) {
+    Json::Value obj;
+    Json::Reader json_reader;
+    Json::FastWriter json_writer;
+    auto str = reinterpret_cast<const char *>(msg);
+    if (!json_reader.parse(str, str + len, obj) < 0) {
         return -EINVAL;
     }
 
-    std::shared_ptr<JSONObject> obj;
-    if (!json.getObject(&obj)) {
+    LOG(VERBOSE) << obj.toStyledString();
+
+    if (!obj.isMember("type")) {
         return -EINVAL;
     }
-
-    LOG(VERBOSE) << obj->toString();
-
-    std::string type;
-    if (!obj->getString("type", &type)) {
-        return -EINVAL;
-    }
+    std::string type = obj["type"].asString();
 
     if (type == "greeting") {
-        std::shared_ptr<JSONObject> reply(new JSONObject);
-        reply->setString("type", "hello");
-        reply->setString("reply", "Right back at ya!");
+        Json::Value reply;
+        reply["type"] = "hello";
+        reply["reply"] = "Right back at ya!";
 
-        auto replyAsString = reply->toString();
+        auto replyAsString = json_writer.write(reply);
         sendMessage(replyAsString.c_str(), replyAsString.size());
 
-        std::string value;
-        if (obj->getString("path", &value)) {
-            parseOptions(value);
+        if (obj.isMember("path")) {
+            parseOptions(obj["path"].asString());
         }
 
         if (mOptions & OptionBits::useSingleCertificateForAllTracks) {
@@ -74,12 +69,11 @@
 
         prepareSessions();
     } else if (type == "set-remote-desc") {
-        std::string value;
-        if (!obj->getString("sdp", &value)) {
+        if (!obj.isMember("sdp")) {
             return -EINVAL;
         }
 
-        int err = mOfferedSDP.setTo(value);
+        int err = mOfferedSDP.setTo(obj["sdp"].asString());
 
         if (err) {
             LOG(ERROR) << "Offered SDP could not be parsed (" << err << ")";
@@ -214,32 +208,33 @@
 "a=fmtp:webrtc-datachannel max-message-size=65536\r\n";
         }
 
-        std::shared_ptr<JSONObject> reply(new JSONObject);
-        reply->setString("type", "offer");
-        reply->setString("sdp", ss.str());
+        Json::Value reply;
+        reply["type"] = "offer";
+        reply["sdp"] = ss.str();
 
-        auto replyAsString = reply->toString();
+        auto replyAsString = json_writer.write(reply);
         sendMessage(replyAsString.c_str(), replyAsString.size());
     } else if (type == "get-ice-candidate") {
-        int32_t mid;
-        CHECK(obj->getInt32("mid", &mid));
+        CHECK(obj.isMember("mid"));
+        int32_t mid = obj["mid"].asInt();
 
         bool success = getCandidate(mid);
 
         if (!success) {
-            std::shared_ptr<JSONObject> reply(new JSONObject);
-            reply->setString("type", "ice-candidate");
+            Json::Value reply;
+            reply["type"] = "ice-candidate";
 
-            auto replyAsString = reply->toString();
+            auto replyAsString = json_writer.write(reply);
             sendMessage(replyAsString.c_str(), replyAsString.size());
         }
     } else if (type == "set-mouse-position") {
-        int32_t down;
-        CHECK(obj->getInt32("down", &down));
+        CHECK(obj.isMember("down"));
+        int32_t down = obj["down"].asInt();
 
-        int32_t x, y;
-        CHECK(obj->getInt32("x", &x));
-        CHECK(obj->getInt32("y", &y));
+        CHECK(obj.isMember("x"));
+        CHECK(obj.isMember("y"));
+        int32_t x = obj["x"].asInt();
+        int32_t y = obj["y"].asInt();
 
         LOG(VERBOSE)
             << "set-mouse-position(" << down << ", " << x << ", " << y << ")";
@@ -252,12 +247,16 @@
 
         mTouchSink->onAccessUnit(accessUnit);
     } else if (type == "inject-multi-touch") {
-        int32_t id, initialDown, x, y, slot;
-        CHECK(obj->getInt32("id", &id));
-        CHECK(obj->getInt32("initialDown", &initialDown));
-        CHECK(obj->getInt32("x", &x));
-        CHECK(obj->getInt32("y", &y));
-        CHECK(obj->getInt32("slot", &slot));
+        CHECK(obj.isMember("id"));
+        CHECK(obj.isMember("initialDown"));
+        CHECK(obj.isMember("x"));
+        CHECK(obj.isMember("y"));
+        CHECK(obj.isMember("slot"));
+        int32_t id = obj["id"].asInt();
+        int32_t initialDown = obj["initialDown"].asInt();
+        int32_t x = obj["x"].asInt();
+        int32_t y = obj["y"].asInt();
+        int32_t slot = obj["slot"].asInt();
 
         LOG(VERBOSE)
             << "inject-multi-touch id="
@@ -383,24 +382,24 @@
 
     auto rtp = mRTPs.back();
 
-    std::shared_ptr<JSONObject> reply(new JSONObject);
-    reply->setString("type", "ice-candidate");
+    Json::Value reply;
+    reply["type"] = "ice-candidate";
 
     auto localIPString = rtp->getLocalIPString();
 
     // see rfc8445, 5.1.2.1. for the derivation of "2122121471" below.
-    reply->setString(
-            "candidate",
+    reply["candidate"] =
                 "candidate:0 1 UDP 2122121471 "
                 + localIPString
                 + " "
                 + std::to_string(rtp->getLocalPort())
                 + " typ host generation 0 ufrag "
-                + rtp->getLocalUFrag());
+                + rtp->getLocalUFrag();
 
-    reply->setInt32("mlineIndex", mlineIndex);
+    reply["mlineIndex"] = static_cast<Json::UInt64>(mlineIndex);
 
-    auto replyAsString = reply->toString();
+    Json::FastWriter json_writer;
+    auto replyAsString = json_writer.write(reply);
     sendMessage(replyAsString.c_str(), replyAsString.size());
 
     return true;
diff --git a/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h b/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h
index 8ca64d8..03b6764 100644
--- a/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h
+++ b/host/frontend/gcastv2/webrtc/include/webrtc/MyWebSocketHandler.h
@@ -7,7 +7,6 @@
 
 #include <https/WebSocketHandler.h>
 #include <https/RunLoop.h>
-#include <media/stagefright/foundation/JSONObject.h>
 #include <source/StreamingSink.h>
 
 #include <memory>
@@ -31,8 +30,6 @@
             uint8_t headerByte, const uint8_t *msg, size_t len) override;
 
 private:
-    using JSONObject = android::JSONObject;
-
     enum OptionBits : uint32_t {
         disableAudio                        = 1,
         bundleTracks                        = 2,