179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong/*
279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Copyright 2011, The Android Open Source Project
379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Licensed under the Apache License, Version 2.0 (the "License");
579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * you may not use this file except in compliance with the License.
679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * You may obtain a copy of the License at
779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *     http://www.apache.org/licenses/LICENSE-2.0
979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
1079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Unless required by applicable law or agreed to in writing, software
1179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * distributed under the License is distributed on an "AS IS" BASIS,
1279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * See the License for the specific language governing permissions and
1479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * limitations under the License.
1579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong */
1679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
1779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong// #define LOG_NDEBUG 0
1879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#define LOG_TAG "AndroidMediaUtils"
1979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
2079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#include <utils/Log.h>
2179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#include "android_media_Utils.h"
2279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
2388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
290ab416269a866c8afa8f65d9351afa2407abee4cZhijun He#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
300ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
3179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongnamespace android {
3279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
336e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung ChungAssetStream::AssetStream(SkStream* stream)
342584cda885964370f612a2b9251f7d6cf9ebf29aSungsoo Lim    : mStream(stream), mPosition(0) {
356e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
366e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
376e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung ChungAssetStream::~AssetStream() {
386e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
396e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
406e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chungpiex::Error AssetStream::GetData(
416e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        const size_t offset, const size_t length, std::uint8_t* data) {
426e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    // Seek first.
436e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    if (mPosition != offset) {
446e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        if (!mStream->seek(offset)) {
456e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung            return piex::Error::kFail;
466e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        }
476e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    }
486e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
496e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    // Read bytes.
506e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    size_t size = mStream->read((void*)data, length);
512584cda885964370f612a2b9251f7d6cf9ebf29aSungsoo Lim    mPosition = offset + size;
526e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
536e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    return size == length ? piex::Error::kOk : piex::Error::kFail;
546e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
556e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
566e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung ChungBufferedStream::BufferedStream(SkStream* stream)
576e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    : mStream(stream) {
586e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
596e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
606e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung ChungBufferedStream::~BufferedStream() {
616e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
626e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
636e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chungpiex::Error BufferedStream::GetData(
646e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        const size_t offset, const size_t length, std::uint8_t* data) {
656e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    // Seek first.
666e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    if (offset + length > mStreamBuffer.bytesWritten()) {
676e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        size_t sizeToRead = offset + length - mStreamBuffer.bytesWritten();
686e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        if (sizeToRead <= kMinSizeToRead) {
696e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung            sizeToRead = kMinSizeToRead;
706e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        }
71cad166686787a494b6689b8adb013e016adfcd90Yujie Qin
726e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        void* tempBuffer = malloc(sizeToRead);
73cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        if (tempBuffer == NULL) {
74cad166686787a494b6689b8adb013e016adfcd90Yujie Qin          return piex::Error::kFail;
75cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        }
76cad166686787a494b6689b8adb013e016adfcd90Yujie Qin
77cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        size_t bytesRead = mStream->read(tempBuffer, sizeToRead);
78cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        if (bytesRead != sizeToRead) {
796e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung            free(tempBuffer);
80cad166686787a494b6689b8adb013e016adfcd90Yujie Qin            return piex::Error::kFail;
816e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        }
82cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        mStreamBuffer.write(tempBuffer, bytesRead);
83cad166686787a494b6689b8adb013e016adfcd90Yujie Qin        free(tempBuffer);
846e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    }
856e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
866e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    // Read bytes.
876e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    if (mStreamBuffer.read((void*)data, offset, length)) {
886e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        return piex::Error::kOk;
896e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    } else {
906e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        return piex::Error::kFail;
916e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    }
926e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung}
936e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung
9415ef59e081846b43660635391d536361c3253a22Jaesung ChungFileStream::FileStream(const int fd)
956e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    : mPosition(0) {
9615ef59e081846b43660635391d536361c3253a22Jaesung Chung    mFile = fdopen(fd, "r");
9715ef59e081846b43660635391d536361c3253a22Jaesung Chung    if (mFile == NULL) {
9815ef59e081846b43660635391d536361c3253a22Jaesung Chung        return;
9915ef59e081846b43660635391d536361c3253a22Jaesung Chung    }
10015ef59e081846b43660635391d536361c3253a22Jaesung Chung}
10115ef59e081846b43660635391d536361c3253a22Jaesung Chung
1028409c0691fb128fef6244305977342776bddf919Jaesung ChungFileStream::FileStream(const String8 filename)
1036e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung    : mPosition(0) {
1048409c0691fb128fef6244305977342776bddf919Jaesung Chung    mFile = fopen(filename.string(), "r");
1058409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile == NULL) {
1068409c0691fb128fef6244305977342776bddf919Jaesung Chung        return;
1078409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1088409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1098409c0691fb128fef6244305977342776bddf919Jaesung Chung
1108409c0691fb128fef6244305977342776bddf919Jaesung ChungFileStream::~FileStream() {
1118409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile != NULL) {
1128409c0691fb128fef6244305977342776bddf919Jaesung Chung        fclose(mFile);
1138409c0691fb128fef6244305977342776bddf919Jaesung Chung        mFile = NULL;
1148409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1158409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1168409c0691fb128fef6244305977342776bddf919Jaesung Chung
1178409c0691fb128fef6244305977342776bddf919Jaesung Chungpiex::Error FileStream::GetData(
1188409c0691fb128fef6244305977342776bddf919Jaesung Chung        const size_t offset, const size_t length, std::uint8_t* data) {
1198409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile == NULL) {
1208409c0691fb128fef6244305977342776bddf919Jaesung Chung        return piex::Error::kFail;
1218409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1228409c0691fb128fef6244305977342776bddf919Jaesung Chung
1238409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Seek first.
1248409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mPosition != offset) {
1258409c0691fb128fef6244305977342776bddf919Jaesung Chung        fseek(mFile, offset, SEEK_SET);
1268409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1278409c0691fb128fef6244305977342776bddf919Jaesung Chung
1288409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Read bytes.
1298409c0691fb128fef6244305977342776bddf919Jaesung Chung    size_t size = fread((void*)data, sizeof(std::uint8_t), length, mFile);
1308409c0691fb128fef6244305977342776bddf919Jaesung Chung    mPosition += size;
1318409c0691fb128fef6244305977342776bddf919Jaesung Chung
132cad166686787a494b6689b8adb013e016adfcd90Yujie Qin    // Handle errors and verify the size.
133cad166686787a494b6689b8adb013e016adfcd90Yujie Qin    if (ferror(mFile) || size != length) {
1348409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("GetData read failed: (offset: %zu, length: %zu)", offset, length);
1358409c0691fb128fef6244305977342776bddf919Jaesung Chung        return piex::Error::kFail;
1368409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1378409c0691fb128fef6244305977342776bddf919Jaesung Chung    return piex::Error::kOk;
1388409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1398409c0691fb128fef6244305977342776bddf919Jaesung Chung
1408409c0691fb128fef6244305977342776bddf919Jaesung Chungbool FileStream::exists() const {
1418409c0691fb128fef6244305977342776bddf919Jaesung Chung    return mFile != NULL;
1428409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1438409c0691fb128fef6244305977342776bddf919Jaesung Chung
1448409c0691fb128fef6244305977342776bddf919Jaesung Chungbool GetExifFromRawImage(
1456e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        piex::StreamInterface* stream, const String8& filename,
1466e08d2b082acfc773907733f2ddab4e9b60616e1Jaesung Chung        piex::PreviewImageData& image_data) {
1478f7a8f1eba590f4a0bb21988fc2a876dcb72dccdAnton Daubert    // Reset the PreviewImageData to its default.
1488f7a8f1eba590f4a0bb21988fc2a876dcb72dccdAnton Daubert    image_data = piex::PreviewImageData();
1498409c0691fb128fef6244305977342776bddf919Jaesung Chung
1508409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (!piex::IsRaw(stream)) {
1518409c0691fb128fef6244305977342776bddf919Jaesung Chung        // Format not supported.
1528409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("Format not supported: %s", filename.string());
1538409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
1548409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1558409c0691fb128fef6244305977342776bddf919Jaesung Chung
1568409c0691fb128fef6244305977342776bddf919Jaesung Chung    piex::Error err = piex::GetPreviewImageData(stream, &image_data);
1578409c0691fb128fef6244305977342776bddf919Jaesung Chung
1588409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (err != piex::Error::kOk) {
1598409c0691fb128fef6244305977342776bddf919Jaesung Chung        // The input data seems to be broken.
1608409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("Raw image not detected: %s (piex error code: %d)", filename.string(), (int32_t)err);
1618409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
1628409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1638409c0691fb128fef6244305977342776bddf919Jaesung Chung
1648409c0691fb128fef6244305977342776bddf919Jaesung Chung    return true;
1658409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1668409c0691fb128fef6244305977342776bddf919Jaesung Chung
16779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongbool ConvertKeyValueArraysToKeyedVector(
16879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        JNIEnv *env, jobjectArray keys, jobjectArray values,
16979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        KeyedVector<String8, String8>* keyedVector) {
17079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
17179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    int nKeyValuePairs = 0;
17279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    bool failed = false;
17379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (keys != NULL && values != NULL) {
17479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        nKeyValuePairs = env->GetArrayLength(keys);
17579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = (nKeyValuePairs != env->GetArrayLength(values));
17679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
17779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
17879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (!failed) {
17979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = ((keys != NULL && values == NULL) ||
18079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong                  (keys == NULL && values != NULL));
18179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
18279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
18379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (failed) {
1843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("keys and values arrays have different length");
18579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
18679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        return false;
18779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
18879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
18979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    for (int i = 0; i < nKeyValuePairs; ++i) {
19079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // No need to check on the ArrayIndexOutOfBoundsException, since
19179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // it won't happen here.
19279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring key = (jstring) env->GetObjectArrayElement(keys, i);
19379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring value = (jstring) env->GetObjectArrayElement(values, i);
19479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
19579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* keyStr = env->GetStringUTFChars(key, NULL);
19679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!keyStr) {  // OutOfMemoryError
19779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
19879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
19979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
20079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* valueStr = env->GetStringUTFChars(value, NULL);
20179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!valueStr) {  // OutOfMemoryError
20279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            env->ReleaseStringUTFChars(key, keyStr);
20379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
20479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
20579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
20679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        keyedVector->add(String8(keyStr), String8(valueStr));
20779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
20879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(key, keyStr);
20979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(value, valueStr);
21079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(key);
21179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(value);
21279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
21379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    return true;
21479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}
21579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeIntegerObject(JNIEnv *env, int32_t value) {
2178d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Integer"));
2188d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2208d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID integerConstructID =
2218d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(I)V");
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(integerConstructID != NULL);
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2248d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), integerConstructID, value);
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic jobject makeLongObject(JNIEnv *env, int64_t value) {
2288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Long"));
2298d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
23007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
2318d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID longConstructID = env->GetMethodID(clazz.get(), "<init>", "(J)V");
23207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    CHECK(longConstructID != NULL);
23307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
2348d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), longConstructID, value);
23507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
23607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeFloatObject(JNIEnv *env, float value) {
2388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Float"));
2398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID floatConstructID =
2428d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(F)V");
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatConstructID != NULL);
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), floatConstructID, value);
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeByteBufferObject(
24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const void *data, size_t size) {
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jbyteArray byteArrayObj = env->NewByteArray(size);
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2538d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/nio/ByteBuffer"));
2548d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID byteBufWrapID =
2578d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticMethodID(
2588d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                clazz.get(), "wrap", "([B)Ljava/nio/ByteBuffer;");
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufWrapID != NULL);
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject byteBufObj = env->CallStaticObjectMethod(
2628d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            clazz.get(), byteBufWrapID, byteArrayObj);
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return byteBufObj;
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
269b842599e51e2d3611503c3c7db1111358f99186dAndreas Huberstatic void SetMapInt32(
270b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        JNIEnv *env, jobject hashMapObj, jmethodID hashMapPutID,
271b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        const char *key, int32_t value) {
272b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jstring keyObj = env->NewStringUTF(key);
273b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jobject valueObj = makeIntegerObject(env, value);
274b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
2755a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe    env->CallObjectMethod(hashMapObj, hashMapPutID, keyObj, valueObj);
276b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
277b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(valueObj); valueObj = NULL;
278b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(keyObj); keyObj = NULL;
279b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber}
280b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertMessageToMap(
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
2838d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> hashMapClazz(
2848d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/util/HashMap"));
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2868d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    if (hashMapClazz.get() == NULL) {
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapConstructID =
2918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapConstructID == NULL) {
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapPutID =
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(
2998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                hashMapClazz.get(),
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "put",
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapPutID == NULL) {
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3078d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < msg->countEntries(); ++i) {
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AMessage::Type valueType;
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *key = msg->getEntryNameAt(i, &valueType);
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
313c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar        if (!strncmp(key, "android._", 9)) {
314c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar            // don't expose private keys (starting with android._)
315c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar            continue;
316c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar        }
317c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = NULL;
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        switch (valueType) {
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeInt32:
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                int32_t val;
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findInt32(key, &val));
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeIntegerObject(env, val);
32707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                break;
32807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            }
32907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
33007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            case AMessage::kTypeInt64:
33107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            {
33207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                int64_t val;
33307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                CHECK(msg->findInt64(key, &val));
33407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
33507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                valueObj = makeLongObject(env, val);
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeFloat:
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                float val;
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findFloat(key, &val));
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeFloatObject(env, val);
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeString:
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                AString val;
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findString(key, &val));
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = env->NewStringUTF(val.c_str());
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3575c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber            case AMessage::kTypeBuffer:
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
3595c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                sp<ABuffer> buffer;
3605c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                CHECK(msg->findBuffer(key, &buffer));
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeByteBufferObject(
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        env, buffer->data(), buffer->size());
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
367b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            case AMessage::kTypeRect:
368b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            {
369b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                int32_t left, top, right, bottom;
370b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                CHECK(msg->findRect(key, &left, &top, &right, &bottom));
371b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
372b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
373b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
374b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
375b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
376f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-left", key).c_str(),
377b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        left);
378b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
379b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
380b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
381b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
382b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
383f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-top", key).c_str(),
384b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        top);
385b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
386b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
387b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
388b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
389b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
390f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-right", key).c_str(),
391b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        right);
392b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
393b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
394b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
395b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
396b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
397f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-bottom", key).c_str(),
398b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        bottom);
399b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                break;
400b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            }
401b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            default:
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (valueObj != NULL) {
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jstring keyObj = env->NewStringUTF(key);
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4095a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe            env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(keyObj); keyObj = NULL;
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(valueObj); valueObj = NULL;
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *map = hashMap;
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertKeyValueArraysToMessage(
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobjectArray keys, jobjectArray values,
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        sp<AMessage> *out) {
4248d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String"));
4258d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(stringClass.get() != NULL);
4268d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> integerClass(env, env->FindClass("java/lang/Integer"));
4278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(integerClass.get() != NULL);
4288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> longClass(env, env->FindClass("java/lang/Long"));
4298d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(longClass.get() != NULL);
4308d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> floatClass(env, env->FindClass("java/lang/Float"));
4318d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(floatClass.get() != NULL);
4328d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
4338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteBufClass.get() != NULL);
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg = new AMessage;
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jsize numEntries = 0;
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (keys != NULL) {
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (values == NULL) {
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        numEntries = env->GetArrayLength(keys);
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (numEntries != env->GetArrayLength(values)) {
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (values != NULL) {
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (jsize i = 0; i < numEntries; ++i) {
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject keyObj = env->GetObjectArrayElement(keys, i);
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4568d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        if (!env->IsInstanceOf(keyObj, stringClass.get())) {
45788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
45888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL);
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (tmp == NULL) {
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -ENOMEM;
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AString key = tmp;
46788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->ReleaseStringUTFChars((jstring)keyObj, tmp);
46988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        tmp = NULL;
47088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
471c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar        if (key.startsWith("android._")) {
472c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar            // don't propagate private keys (starting with android._)
473c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar            continue;
474c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar        }
475c04399feab8e51531975a4b404327511b094bbf6Lajos Molnar
47688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = env->GetObjectArrayElement(values, i);
47788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4788d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        if (env->IsInstanceOf(valueObj, stringClass.get())) {
47988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
48088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (value == NULL) {
48288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                return -ENOMEM;
48388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
48488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setString(key.c_str(), value);
48688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->ReleaseStringUTFChars((jstring)valueObj, value);
48888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            value = NULL;
4898d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, integerClass.get())) {
49088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID intValueID =
4918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(integerClass.get(), "intValue", "()I");
49288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(intValueID != NULL);
49388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint value = env->CallIntMethod(valueObj, intValueID);
49588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setInt32(key.c_str(), value);
4978d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, longClass.get())) {
4988d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            jmethodID longValueID =
4998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(longClass.get(), "longValue", "()J");
5008d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            CHECK(longValueID != NULL);
5018d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
5028d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            jlong value = env->CallLongMethod(valueObj, longValueID);
5038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
5048d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            msg->setInt64(key.c_str(), value);
5058d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, floatClass.get())) {
50688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID floatValueID =
5078d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(floatClass.get(), "floatValue", "()F");
50888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(floatValueID != NULL);
50988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jfloat value = env->CallFloatMethod(valueObj, floatValueID);
51188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setFloat(key.c_str(), value);
5138d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, byteBufClass.get())) {
51488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID positionID =
5158d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(byteBufClass.get(), "position", "()I");
51688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(positionID != NULL);
51788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID limitID =
5198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(byteBufClass.get(), "limit", "()I");
52088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(limitID != NULL);
52188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint position = env->CallIntMethod(valueObj, positionID);
52388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint limit = env->CallIntMethod(valueObj, limitID);
52488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            sp<ABuffer> buffer = new ABuffer(limit - position);
52688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            void *data = env->GetDirectBufferAddress(valueObj);
52888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (data != NULL) {
53088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                memcpy(buffer->data(),
53188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       (const uint8_t *)data + position,
53288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       buffer->size());
53388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            } else {
53488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jmethodID arrayID =
5358d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                    env->GetMethodID(byteBufClass.get(), "array", "()[B");
53688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(arrayID != NULL);
53788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jbyteArray byteArray =
53988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    (jbyteArray)env->CallObjectMethod(valueObj, arrayID);
54088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(byteArray != NULL);
54188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetByteArrayRegion(
54388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        byteArray,
54488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        position,
54588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        buffer->size(),
54688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        (jbyte *)buffer->data());
54788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->DeleteLocalRef(byteArray); byteArray = NULL;
54988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
55088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5519b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber            msg->setBuffer(key.c_str(), buffer);
55288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
55388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
55488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
55588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *out = msg;
55688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
55788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
55888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
55988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5600ab416269a866c8afa8f65d9351afa2407abee4cZhijun He// -----------Utility functions used by ImageReader/Writer JNI-----------------
5610ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5620ab416269a866c8afa8f65d9351afa2407abee4cZhijun Heenum {
5630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    IMAGE_MAX_NUM_PLANES = 3,
5640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He};
5650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5660ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hebool usingRGBAToJpegOverride(int32_t imageFormat,
5670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int32_t containerFormat) {
5680ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
5690ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
5700ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5710ab416269a866c8afa8f65d9351afa2407abee4cZhijun Heint32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
5720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
5730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // write limitations for some platforms (b/17379185).
5740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
5750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return HAL_PIXEL_FORMAT_BLOB;
5760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
5770ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return containerFormat;
5780ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
5790ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5800ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hebool isFormatOpaque(int format) {
5810ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // This is the only opaque format exposed in the ImageFormat public API.
5820ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
5830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
5840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
5850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
5860ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5870ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hebool isPossiblyYUV(PixelFormat format) {
5880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    switch (static_cast<int>(format)) {
5890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RGBA_8888:
5900ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RGBX_8888:
5910ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RGB_888:
5920ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RGB_565:
5930ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_BGRA_8888:
5940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_Y8:
5950ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_Y16:
5960ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RAW16:
5970ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RAW10:
5980ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
5990ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_BLOB:
6000ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
6010ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            return false;
6020ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6030ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YV12:
6040ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YCbCr_420_888:
6050ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
6060ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        default:
6070ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            return true;
6080ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
6090ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
6100ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6110ab416269a866c8afa8f65d9351afa2407abee4cZhijun Heuint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) {
6120ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s", __FUNCTION__);
6130ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
6140ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint32_t size = 0;
6150ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint32_t width = buffer->width;
6160ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint8_t* jpegBuffer = buffer->data;
6170ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6180ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (usingRGBAOverride) {
6190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
6200ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
6210ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6220ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // First check for JPEG transport header at the end of the buffer
6230ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
6240ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
6250ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
6260ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        size = blob->jpeg_size;
6270ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
6280ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
6290ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6300ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // failed to find size, default to whole buffer
6310ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (size == 0) {
6320ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        /*
6330ab416269a866c8afa8f65d9351afa2407abee4cZhijun He         * This is a problem because not including the JPEG header
6340ab416269a866c8afa8f65d9351afa2407abee4cZhijun He         * means that in certain rare situations a regular JPEG blob
6350ab416269a866c8afa8f65d9351afa2407abee4cZhijun He         * will be mis-identified as having a header, in which case
6360ab416269a866c8afa8f65d9351afa2407abee4cZhijun He         * we will get a garbage size value.
6370ab416269a866c8afa8f65d9351afa2407abee4cZhijun He         */
6380ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
6390ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                __FUNCTION__, width);
6400ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        size = width;
6410ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
6420ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6430ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return size;
6440ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
6450ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6460ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatus_t getLockedImageInfo(LockedImage* buffer, int idx,
6470ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
6480ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s", __FUNCTION__);
6490ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
6500ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
6510ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
6520ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
6530ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
6540ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
6550ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6560ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
6570ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6580ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint32_t dataSize, ySize, cSize, cStride;
6590ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint32_t pStride = 0, rStride = 0;
6600ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint8_t *cb, *cr;
6610ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint8_t *pData = NULL;
6620ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    int bytesPerPixel = 0;
6630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    dataSize = ySize = cSize = cStride = 0;
6650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    int32_t fmt = buffer->flexFormat;
6660ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
6680ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    fmt = applyFormatOverrides(fmt, containerFormat);
6690ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    switch (fmt) {
6700ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YCbCr_420_888:
6710ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            pData =
6720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 0) ?
6730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    buffer->data :
6740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 1) ?
6750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    buffer->dataCb :
6760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                buffer->dataCr;
6770ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            // only map until last pixel
6780ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            if (idx == 0) {
6790ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                pStride = 1;
6800ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                rStride = buffer->stride;
6810ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
6820ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            } else {
6830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                pStride = buffer->chromaStep;
6840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                rStride = buffer->chromaStride;
6850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
6860ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
6870ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            }
6880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            break;
6890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // NV21
6900ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
6910ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cr = buffer->data + (buffer->stride * buffer->height);
6920ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cb = cr + 1;
6930ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            // only map until last pixel
6940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            ySize = buffer->width * (buffer->height - 1) + buffer->width;
6950ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
6960ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6970ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            pData =
6980ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 0) ?
6990ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    buffer->data :
7000ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 1) ?
7010ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    cb:
7020ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                cr;
7030ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
7040ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            dataSize = (idx == 0) ? ySize : cSize;
7050ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            pStride = (idx == 0) ? 1 : 2;
7060ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            rStride = buffer->width;
7070ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            break;
7080ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        case HAL_PIXEL_FORMAT_YV12:
7090ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            // Y and C stride need to be 16 pixel aligned.
7100ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
7110ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                                "Stride is not 16 pixel aligned %d", buffer->stride);
7120ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
7130ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            ySize = buffer->stride * buffer->height;
7140ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cStride = ALIGN(buffer->stride / 2, 16);
7150ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cr = buffer->data + ySize;
7160ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cSize = cStride * buffer->height / 2;
7170ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            cb = cr + cSize;
7180ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
7190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            pData =
7200ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 0) ?
7210ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    buffer->data :
7220ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (idx == 1) ?
7230ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    cb :
7240ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                cr;
7250ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            dataSize = (idx == 0) ? ySize : cSize;
7260ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            pStride = 1;
7270ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
7280ab416269a86