134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/*
234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectCopyright (c) 2008, The Android Open Source Project
434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectAll rights reserved.
534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectRedistribution and use in source and binary forms, with or without
734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectmodification, are permitted provided that the following conditions
834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectare met:
934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Redistributions of source code must retain the above copyright
1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project   notice, this list of conditions and the following disclaimer.
1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Redistributions in binary form must reproduce the above copyright
1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project   notice, this list of conditions and the following disclaimer in
13db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync   the documentation and/or other materials provided with the
1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project   distribution.
1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Neither the name of Google, Inc. nor the names of its contributors
1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project   may be used to endorse or promote products derived from this
1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project   software without specific prior written permission.
1834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
1934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectFOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectCOPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo syncOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectAND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectSUCH DAMAGE.
3134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project*/
3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <nativehelper/JNIHelp.h>
3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <nativehelper/jni.h>
3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <assert.h>
38189fc1d078bf9bb74fa74645b6d6c4e3b58da001Dongwon Kang#include <ctype.h>
3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <dlfcn.h>
4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <stdio.h>
4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <string.h>
4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <sys/stat.h>
4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <utils/Log.h>
4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h"
4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifndef NELEM
4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))
4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Define the line below to turn on poor man's debugging output
5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef SUPERDEBUG
5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Various tests
5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef REALLOCTEST
5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef OUTOFMEMORYTEST1
5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void addExifAttibute(JNIEnv *env, jmethodID putMethod, jobject hashMap, char* key, char* value) {
5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jstring jkey = (*env)->NewStringUTF(env, key);
6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jstring jvalue = (*env)->NewStringUTF(env, value);
6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, putMethod, jkey, jvalue);
6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    (*env)->ReleaseStringUTFChars(env, jkey, key);
6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    (*env)->ReleaseStringUTFChars(env, jvalue, value);
6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectextern void ResetJpgfile();
6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int loadExifInfo(const char* FileName, int readJPG) {
7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
727a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("loadExifInfo");
7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int Modified = FALSE;
7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ReadMode_t ReadMode = READ_METADATA;
7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (readJPG) {
7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // Must add READ_IMAGE else we can't write the JPG back out.
7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        ReadMode |= READ_IMAGE;
7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
827a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("ResetJpgfile");
8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ResetJpgfile();
8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Start with an empty image information structure.
8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    memset(&ImageInfo, 0, sizeof(ImageInfo));
8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ImageInfo.FlashUsed = -1;
8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ImageInfo.MeteringMode = -1;
9034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ImageInfo.Whitebalance = -1;
91db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Store file date/time.
9334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    {
9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        struct stat st;
9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (stat(FileName, &st) >= 0) {
9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ImageInfo.FileDateTime = st.st_mtime;
9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ImageInfo.FileSize = st.st_size;
9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
10034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    strncpy(ImageInfo.FileName, FileName, PATH_MAX);
10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1037a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("ReadJpegFile");
10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return ReadJpegFile(FileName, ReadMode);
10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
10734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveJPGFile(const char* filename) {
10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char backupName[400];
11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    struct stat buf;
11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1137a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("Modified: %s\n", filename);
11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
11534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    strncpy(backupName, filename, 395);
11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    strcat(backupName, ".t");
11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Remove any .old file name that may pre-exist
12034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1217a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("removing backup %s", backupName);
12234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
12334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    unlink(backupName);
12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Rename the old file.
12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1277a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("rename %s to %s", filename, backupName);
12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
12934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    rename(filename, backupName);
13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Write the new file.
13234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1337a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("WriteJpegFile %s", filename);
13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
13534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (WriteJpegFile(filename)) {
136db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // Copy the access rights from original file
13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1397a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("stating old file %s", backupName);
14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (stat(backupName, &buf) == 0){
14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // set Unix access rights and time to new file
14334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            struct utimbuf mtime;
14434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            chmod(filename, buf.st_mode);
145db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
14634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            mtime.actime = buf.st_mtime;
14734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            mtime.modtime = buf.st_mtime;
148db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            utime(filename, &mtime);
15034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
151db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // Now that we are done, remove original file.
15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1547a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("unlinking old file %s", backupName);
15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        unlink(backupName);
15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1587a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("returning from saveJPGFile");
15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    } else {
16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1627a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("WriteJpegFile failed, restoring from backup file");
16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // move back the backup file
16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        rename(backupName, filename);
16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
16934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid copyThumbnailData(uchar* thumbnailData, int thumbnailLen) {
17034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1717a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** copyThumbnailData\n");
17234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
17334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    Section_t* ExifSection = FindSection(M_EXIF);
17434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ExifSection == NULL) {
17534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return;
17634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
17734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int NewExifSize = ImageInfo.ThumbnailOffset+8+thumbnailLen;
17834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ExifSection->Data = (uchar *)realloc(ExifSection->Data, NewExifSize);
17934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ExifSection->Data == NULL) {
18034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return;
18134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
18234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    uchar* ThumbnailPointer = ExifSection->Data+ImageInfo.ThumbnailOffset+8;
18334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
18434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    memcpy(ThumbnailPointer, thumbnailData, thumbnailLen);
18534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
18634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ImageInfo.ThumbnailSize = thumbnailLen;
18734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
18834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    Put32u(ExifSection->Data+ImageInfo.ThumbnailSizeOffset+8, thumbnailLen);
18934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
19034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ExifSection->Data[0] = (uchar)(NewExifSize >> 8);
19134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ExifSection->Data[1] = (uchar)NewExifSize;
19234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ExifSection->Size = NewExifSize;
19334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
19434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
19534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void saveAttributes(JNIEnv *env, jobject jobj, jstring jfilename, jstring jattributes)
19634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
19734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
1987a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** saveAttributes\n");
19934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
20034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // format of attributes string passed from java:
20134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
20234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // example input: "4 ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
20334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ExifElement_t* exifElementTable = NULL;
20434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* filename = NULL;
20534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    uchar* thumbnailData = NULL;
20634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int attrCnt = 0;
20734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* attributes = (*env)->GetStringUTFChars(env, jattributes, NULL);
20834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (attributes == NULL) {
20934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        goto exit;
21034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
21134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2127a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("attributes %s\n", attributes);
21334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
21434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
21534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Get the number of attributes - it's the first number in the string.
21634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    attrCnt = atoi(attributes);
21734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char* attrPtr = strchr(attributes, ' ') + 1;
21834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2197a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("attribute count %d attrPtr %s\n", attrCnt, attrPtr);
22034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
22134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
22234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Load all the hash exif elements into a more c-like structure
22334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    exifElementTable = malloc(sizeof(ExifElement_t) * attrCnt);
22434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (exifElementTable == NULL) {
22534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        goto exit;
22634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
22734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef OUTOFMEMORYTEST1
22834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    goto exit;
22934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
23034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
23134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int i;
23234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char tag[100];
233482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong    int hasDateTimeTag = FALSE;
23434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int gpsTagCount = 0;
23534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int exifTagCount = 0;
23634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
23734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    for (i = 0; i < attrCnt; i++) {
23834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // get an element from the attribute string and add it to the c structure
23934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // first, extract the attribute name
24034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        char* tagEnd = strchr(attrPtr, '=');
24134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (tagEnd == 0) {
24234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2437a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block            ALOGE("saveAttributes: couldn't find end of tag");
24434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
24534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto exit;
24634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
24734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (tagEnd - attrPtr > 99) {
24834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2497a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block            ALOGE("saveAttributes: attribute tag way too long");
25034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
25134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto exit;
25234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
25334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        memcpy(tag, attrPtr, tagEnd - attrPtr);
25434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        tag[tagEnd - attrPtr] = 0;
25534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
25634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (IsGpsTag(tag)) {
25734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            exifElementTable[i].GpsTag = TRUE;
25834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            exifElementTable[i].Tag = GpsTagNameToValue(tag);
25934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ++gpsTagCount;
26034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        } else {
26134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            exifElementTable[i].GpsTag = FALSE;
26234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            exifElementTable[i].Tag = TagNameToValue(tag);
26334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            ++exifTagCount;
26434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
26534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        attrPtr = tagEnd + 1;
26634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
267482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong        if (IsDateTimeTag(exifElementTable[i].Tag)) {
268482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong            hasDateTimeTag = TRUE;
269482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong        }
270482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong
27134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // next get the length of the attribute value
27234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        int valueLen = atoi(attrPtr);
27334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        attrPtr = strchr(attrPtr, ' ') + 1;
27434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (attrPtr == 0) {
27534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2767a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block            ALOGE("saveAttributes: couldn't find end of value len");
27734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
27834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto exit;
27934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
28034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        exifElementTable[i].Value = malloc(valueLen + 1);
28134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (exifElementTable[i].Value == NULL) {
28234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto exit;
28334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
28434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        memcpy(exifElementTable[i].Value, attrPtr, valueLen);
28534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        exifElementTable[i].Value[valueLen] = 0;
28634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        exifElementTable[i].DataLength = valueLen;
28734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
28834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        attrPtr += valueLen;
28934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
29034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2917a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("tag %s id %d value %s data length=%d isGps=%d", tag, exifElementTable[i].Tag,
29234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            exifElementTable[i].Value, exifElementTable[i].DataLength, exifElementTable[i].GpsTag);
29334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
29434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
29534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
29634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
29734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
2987a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("Call loadAttributes() with filename is %s. Loading exif info\n", filename);
29934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
30034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    loadExifInfo(filename, TRUE);
30134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
30234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
30334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    DumpExifMap = TRUE;
30434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ShowTags = TRUE;
30534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ShowImageInfo(TRUE);
3067a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("create exif 2");
30734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
30834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
30934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // If the jpg file has a thumbnail, preserve it.
31034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int thumbnailLength = ImageInfo.ThumbnailSize;
31134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ThumbnailOffset) {
31234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        Section_t* ExifSection = FindSection(M_EXIF);
31334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ExifSection) {
31434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8;
31534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            thumbnailData = (uchar*)malloc(ImageInfo.ThumbnailSize);
31634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            // if the malloc fails, we just won't copy the thumbnail
31734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (thumbnailData) {
31834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                memcpy(thumbnailData, thumbnailPointer, thumbnailLength);
31934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            }
32034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
32134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
32234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
323482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong    create_EXIF(exifElementTable, exifTagCount, gpsTagCount, hasDateTimeTag);
32434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
32534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (thumbnailData) {
32634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        copyThumbnailData(thumbnailData, thumbnailLength);
32734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
32834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
32934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectexit:
33034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
3317a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("cleaning up now in saveAttributes");
33234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
33334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // try to clean up resources
33434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (attributes) {
33534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->ReleaseStringUTFChars(env, jattributes, attributes);
33634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
33734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (filename) {
33834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->ReleaseStringUTFChars(env, jfilename, filename);
33934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
34034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (exifElementTable) {
34134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // free the table
34234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        for (i = 0; i < attrCnt; i++) {
34334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            free(exifElementTable[i].Value);
34434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
34534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        free(exifElementTable);
34634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
34734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (thumbnailData) {
34834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        free(thumbnailData);
34934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
35034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
3517a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("returning from saveAttributes");
35234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
35334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
35434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Temporarily saving these commented out lines because they represent a lot of figuring out
35534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// patterns for JNI.
35634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get link to Method "entrySet"
35734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID entrySetMethod = (*env)->GetMethodID(env, jclass_of_hashmap, "entrySet", "()Ljava/util/Set;");
35834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
35934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Invoke the "entrySet" method on the HashMap object
36034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jobject jobject_of_entryset = (*env)->CallObjectMethod(env, hashMap, entrySetMethod);
36134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
36234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get the Set Class
36334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jclass jclass_of_set = (*env)->FindClass(env, "java/util/Set");
36434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
36534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    if (jclass_of_set == 0) {
36634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//        printf("java/util/Set lookup failed\n");
36734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//        return;
36834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    }
36934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
37034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get link to Method "iterator"
37134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID iteratorMethod = (*env)->GetMethodID(env, jclass_of_set, "iterator", "()Ljava/util/Iterator;");
37234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
37334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Invoke the "iterator" method on the jobject_of_entryset variable of type Set
37434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jobject jobject_of_iterator = (*env)->CallObjectMethod(env, jobject_of_entryset, iteratorMethod);
37534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
37634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get the "Iterator" class
37734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jclass jclass_of_iterator = (*env)->FindClass(env, "java/util/Iterator");
37834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
37934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get link to Method "hasNext"
38034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID hasNextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "hasNext", "()Z");
38134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
38234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Invoke - Get the value hasNextMethod
38334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jboolean bHasNext = (*env)->CallBooleanMethod(env, jobject_of_iterator, hasNextMethod);
38434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
38534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    // Get link to Method "hasNext"
38634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID nextMethod = (*env)->GetMethodID(env, jclass_of_iterator, "next", "()Ljava/util/Map/Entry;");
38734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
38834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jclass jclass_of_mapentry = (*env)->FindClass(env, "java/util/Map/Entry");
38934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
39034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID getKeyMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getKey", "()Ljava/lang/Object");
39134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//
39234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//    jmethodID getValueMethod = (*env)->GetMethodID(env, jclass_of_mapentry, "getValue", "()Ljava/lang/Object");
39334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
39434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
39534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jboolean appendThumbnail(JNIEnv *env, jobject jobj, jstring jfilename, jstring jthumbnailfilename)
39634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
39734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
3987a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** appendThumbnail\n");
39934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
40034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
40134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
40234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (filename == NULL) {
40334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return JNI_FALSE;
40434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
40534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* thumbnailfilename = (*env)->GetStringUTFChars(env, jthumbnailfilename, NULL);
40634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (thumbnailfilename == NULL) {
40734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return JNI_FALSE;
40834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
40934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG
4107a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block     ALOGE("*******before actual call to ReplaceThumbnail\n");
41134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project     ShowImageInfo(TRUE);
41234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif
41334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ReplaceThumbnail(thumbnailfilename);
41434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #ifdef SUPERDEBUG
41534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project     ShowImageInfo(TRUE);
41634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #endif
41734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    (*env)->ReleaseStringUTFChars(env, jfilename, filename);
41834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    (*env)->ReleaseStringUTFChars(env, jthumbnailfilename, thumbnailfilename);
419db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo sync
42034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    DiscardData();
42134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return JNI_TRUE;
42234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
42334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
42434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void commitChanges(JNIEnv *env, jobject jobj, jstring jfilename)
42534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
42634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
4277a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** commitChanges\n");
42834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
42934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
43034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (filename) {
43134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        saveJPGFile(filename);
4326a3cf8f158c6f0f7e069f8aeb0825a3fefeabd02Chih-Chung Chang        DiscardData();
43334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->ReleaseStringUTFChars(env, jfilename, filename);
43434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
43534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
43634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
43734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jbyteArray getThumbnail(JNIEnv *env, jobject jobj, jstring jfilename)
43834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
43934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
4407a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** getThumbnail\n");
44134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
44234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
44334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
44434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (filename) {
44534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        loadExifInfo(filename, FALSE);
44634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        Section_t* ExifSection = FindSection(M_EXIF);
44734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ExifSection == NULL ||  ImageInfo.ThumbnailSize == 0) {
44834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
4497a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("no exif section or size == 0, so no thumbnail\n");
45034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
45134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto noThumbnail;
45234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
45334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        uchar* thumbnailPointer = ExifSection->Data + ImageInfo.ThumbnailOffset + 8;
45434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
45534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        jbyteArray byteArray = (*env)->NewByteArray(env, ImageInfo.ThumbnailSize);
45634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (byteArray == NULL) {
45734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
4587a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("couldn't allocate thumbnail memory, so no thumbnail\n");
45934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
46034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            goto noThumbnail;
46134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
46234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->SetByteArrayRegion(env, byteArray, 0, ImageInfo.ThumbnailSize, thumbnailPointer);
46334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
4647a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("thumbnail size %d\n", ImageInfo.ThumbnailSize);
46534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
46634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->ReleaseStringUTFChars(env, jfilename, filename);
467eb7bd1066e19b5ef048fda5f756c4bb0bc891f30Jiangping Wu        DiscardData();
46834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return byteArray;
46934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
47034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source ProjectnoThumbnail:
47134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (filename) {
47234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        (*env)->ReleaseStringUTFChars(env, jfilename, filename);
47334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
47434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    DiscardData();
47534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return NULL;
47634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
47734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
47831b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkeystatic jlongArray getThumbnailRange(JNIEnv *env, jobject jobj, jstring jfilename) {
47931b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    jlongArray resultArray = NULL;
48031b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
48131b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    if (filename) {
48231b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        loadExifInfo(filename, FALSE);
48331b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        Section_t* ExifSection = FindSection(M_EXIF);
48431b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        if (ExifSection == NULL || ImageInfo.ThumbnailSize == 0) {
48531b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey            goto done;
48631b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        }
48731b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey
48831b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        jlong result[2];
48931b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        result[0] = ExifSection->Offset + ImageInfo.ThumbnailOffset + 8;
49031b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        result[1] = ImageInfo.ThumbnailSize;
49131b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey
49231b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        resultArray = (*env)->NewLongArray(env, 2);
49331b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        if (resultArray == NULL) {
49431b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey            goto done;
49531b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        }
49631b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey
49731b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        (*env)->SetLongArrayRegion(env, resultArray, 0, 2, result);
49831b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    }
49931b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkeydone:
50031b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    if (filename) {
50131b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey        (*env)->ReleaseStringUTFChars(env, jfilename, filename);
50231b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    }
50331b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    DiscardData();
50431b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey    return resultArray;
50531b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey}
50631b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey
50734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int attributeCount;      // keep track of how many attributes we've added
50834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
50934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length
51034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueString(char** buf, int bufLen, const char* key, const char* value) {
51134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // Appends to buf like this: "ImageLength=4 1024"
51234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
51334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char valueLen[15];
51434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    snprintf(valueLen, 15, "=%d ", (int)strlen(value));
51534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
51634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // check to see if buf has enough room to append
51734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int len = strlen(key) + strlen(valueLen) + strlen(value);
51834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int newLen = strlen(*buf) + len;
51934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (newLen >= bufLen) {
52034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST
52134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = newLen + 5;
5227a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block        ALOGE("reallocing to %d", bufLen);
52334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else
52434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = newLen + 500;
52534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
52634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        *buf = realloc(*buf, bufLen);
52734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (*buf == NULL) {
52834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            return 0;
52934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
53034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
53134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // append the new attribute and value
53234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    snprintf(*buf + strlen(*buf), bufLen, "%s%s%s", key, valueLen, value);
53334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
5347a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("buf %s", *buf);
53534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
53634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ++attributeCount;
53734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return bufLen;
53834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
53934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
54034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length
54134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueInt(char** buf, int bufLen, const char* key, int value) {
54234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char valueStr[20];
54334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    snprintf(valueStr, 20, "%d", value);
54434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
54534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return addKeyValueString(buf, bufLen, key, valueStr);
54634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
54734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
54834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// returns new buffer length
54934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int addKeyValueDouble(char** buf, int bufLen, const char* key, double value, const char* format) {
55034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char valueStr[30];
55134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    snprintf(valueStr, 30, format, value);
55234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
55334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return addKeyValueString(buf, bufLen, key, valueStr);
55434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
55534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
556574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li// Returns new buffer length. Rational value will be appended as "numerator/denominator".
557574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Listatic int addKeyValueRational(char** buf, int bufLen, const char* key, rat_t value) {
558574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li    char valueStr[25];
559574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li    snprintf(valueStr, sizeof(valueStr), "%u/%u", value.num, value.denom);
560574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li    return addKeyValueString(buf, bufLen, key, valueStr);
561574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li}
562574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li
56334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic jstring getAttributes(JNIEnv *env, jobject jobj, jstring jfilename)
56434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
56534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
5667a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("******************************** getAttributes\n");
56734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
56834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
56934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    loadExifInfo(filename, FALSE);
57034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
57134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    ShowImageInfo(TRUE);
57234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
57334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    (*env)->ReleaseStringUTFChars(env, jfilename, filename);
57434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
57534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    attributeCount = 0;
57634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef REALLOCTEST
57734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int bufLen = 5;
57834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#else
57934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int bufLen = 1000;
58034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
58134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char* buf = malloc(bufLen);
58234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (buf == NULL) {
58334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return NULL;
58434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
58534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    *buf = 0;   // start the string out at zero length
58634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
58734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // save a fake "hasThumbnail" tag to pass to the java ExifInterface
58834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    bufLen = addKeyValueString(&buf, bufLen, "hasThumbnail",
58934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        ImageInfo.ThumbnailOffset == 0 || ImageInfo.ThumbnailAtEnd == FALSE || ImageInfo.ThumbnailSize == 0 ?
59034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            "false" : "true");
59134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (bufLen == 0) return NULL;
59234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
59334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.CameraMake[0]) {
59434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueString(&buf, bufLen, "Make", ImageInfo.CameraMake);
59534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
59634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
59734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.CameraModel[0]) {
59834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueString(&buf, bufLen, "Model", ImageInfo.CameraModel);
59934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
60034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
60134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.DateTime[0]) {
60234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueString(&buf, bufLen, "DateTime", ImageInfo.DateTime);
60334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
60434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
60576aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    if (ImageInfo.DigitizedTime[0]) {
60676aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        bufLen = addKeyValueString(&buf, bufLen, "DateTimeDigitized", ImageInfo.DigitizedTime);
60776aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        if (bufLen == 0) return NULL;
60876aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    }
60976aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    if (ImageInfo.SubSecTime[0]) {
61076aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        bufLen = addKeyValueString(&buf, bufLen, "SubSecTime", ImageInfo.SubSecTime);
61176aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        if (bufLen == 0) return NULL;
61276aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    }
61376aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    if (ImageInfo.SubSecTimeOrig[0]) {
61476aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        bufLen = addKeyValueString(&buf, bufLen, "SubSecTimeOriginal", ImageInfo.SubSecTimeOrig);
61576aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        if (bufLen == 0) return NULL;
61676aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    }
61776aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    if (ImageInfo.SubSecTimeDig[0]) {
61876aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        bufLen = addKeyValueString(&buf, bufLen, "SubSecTimeDigitized", ImageInfo.SubSecTimeDig);
61976aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He        if (bufLen == 0) return NULL;
62076aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He    }
62176aba45cce69de1b3a7ba29bbacc5339512de13cZhijun He
62234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    bufLen = addKeyValueInt(&buf, bufLen, "ImageWidth", ImageInfo.Width);
62334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (bufLen == 0) return NULL;
62434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
62534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    bufLen = addKeyValueInt(&buf, bufLen, "ImageLength", ImageInfo.Height);
62634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (bufLen == 0) return NULL;
62734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
62834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    bufLen = addKeyValueInt(&buf, bufLen, "Orientation", ImageInfo.Orientation);
62934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (bufLen == 0) return NULL;
63034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6312856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen    if (ImageInfo.FlashUsed >= 0) {
6322856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen        bufLen = addKeyValueInt(&buf, bufLen, "Flash", ImageInfo.FlashUsed);
6332856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen        if (bufLen == 0) return NULL;
6342856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen    }
63534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
636574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li    if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0) {
637574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li        bufLen = addKeyValueRational(&buf, bufLen, "FocalLength", ImageInfo.FocalLength);
63834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
63934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
64034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
64134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.DigitalZoomRatio > 1.0){
64234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // Digital zoom used.  Shame on you!
64334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueDouble(&buf, bufLen, "DigitalZoomRatio", ImageInfo.DigitalZoomRatio, "%1.3f");
64434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
64534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
64634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
64734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ExposureTime){
64834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        const char* format;
64934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ImageInfo.ExposureTime < 0.010){
65034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            format = "%6.4f";
65134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        } else {
65234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            format = "%5.3f";
65334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
65434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
65534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueDouble(&buf, bufLen, "ExposureTime", (double)ImageInfo.ExposureTime, format);
65634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
65734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
65834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
65934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ApertureFNumber){
6605c8f937269957e6651383e988006824781fd021aYin-Chia Yeh        bufLen = addKeyValueDouble(&buf, bufLen, "FNumber", (double)ImageInfo.ApertureFNumber, "%3.3f");
66134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
66234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
66334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
66434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.Distance){
66534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueDouble(&buf, bufLen, "SubjectDistance", (double)ImageInfo.Distance, "%4.2f");
66634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
66734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
66834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
66934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ISOequivalent){
67034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueInt(&buf, bufLen, "ISOSpeedRatings", ImageInfo.ISOequivalent);
67134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
67234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
67334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
67434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ExposureBias){
67534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // If exposure bias was specified, but set to zero, presumably its no bias at all,
67634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        // so only show it if its nonzero.
67734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueDouble(&buf, bufLen, "ExposureBiasValue", (double)ImageInfo.ExposureBias, "%4.2f");
67834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
67934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
68034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
6812856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen    if (ImageInfo.Whitebalance >= 0) {
6822856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen        bufLen = addKeyValueInt(&buf, bufLen, "WhiteBalance", ImageInfo.Whitebalance);
6832856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen        if (bufLen == 0) return NULL;
6842856a2765bf15a8677a481cf8a38d0ad17f31a6eRay Chen    }
68534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
68634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    bufLen = addKeyValueInt(&buf, bufLen, "LightSource", ImageInfo.LightSource);
68734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (bufLen == 0) return NULL;
68834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
68934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
69034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.MeteringMode) {
69134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueInt(&buf, bufLen, "MeteringMode", ImageInfo.MeteringMode);
69234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
69334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
69434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
69534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ExposureProgram) {
69634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueInt(&buf, bufLen, "ExposureProgram", ImageInfo.ExposureProgram);
69734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
69834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
69934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
70034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.ExposureMode) {
70134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueInt(&buf, bufLen, "ExposureMode", ImageInfo.ExposureMode);
70234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
70334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
70434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
70534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.GpsInfoPresent) {
7068d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        if (ImageInfo.GpsLatRaw[0]) {
7078d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSLatitude", ImageInfo.GpsLatRaw);
7088d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            if (bufLen == 0) return NULL;
7098d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        }
7108d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        if (ImageInfo.GpsLatRef[0]) {
7118d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSLatitudeRef", ImageInfo.GpsLatRef);
7128d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            if (bufLen == 0) return NULL;
7138d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        }
7148d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        if (ImageInfo.GpsLongRaw[0]) {
7158d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSLongitude", ImageInfo.GpsLongRaw);
7168d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            if (bufLen == 0) return NULL;
7178d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        }
7188d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        if (ImageInfo.GpsLongRef[0]) {
7198d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSLongitudeRef", ImageInfo.GpsLongRef);
7208d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen            if (bufLen == 0) return NULL;
7218d61723fea0a5cdcd08e34325123fbd3e0bd41aeRay Chen        }
72234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (ImageInfo.GpsAlt[0]) {
7231ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li            bufLen = addKeyValueRational(&buf, bufLen, "GPSAltitude", ImageInfo.GpsAltRaw);
7241ed8197f0cefb2541f630830993e109c59ba822cWu-cheng Li            bufLen = addKeyValueInt(&buf, bufLen, "GPSAltitudeRef", ImageInfo.GpsAltRef);
72534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            if (bufLen == 0) return NULL;
72634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        }
727a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen        if (ImageInfo.GpsDateStamp[0]) {
728a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSDateStamp", ImageInfo.GpsDateStamp);
729a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen            if (bufLen == 0) return NULL;
730a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen        }
731a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen        if (ImageInfo.GpsTimeStamp[0]) {
732a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSTimeStamp", ImageInfo.GpsTimeStamp);
733a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen            if (bufLen == 0) return NULL;
734a39920ca4b96a456511fa32ba90c77f119a274c3Ray Chen        }
735434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen        if (ImageInfo.GpsProcessingMethod[0]) {
736434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen            bufLen = addKeyValueString(&buf, bufLen, "GPSProcessingMethod", ImageInfo.GpsProcessingMethod);
737434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen            if (bufLen == 0) return NULL;
738434623a0e87c8e145dbb46917b4ab9777475d9ebRay Chen        }
73934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
74034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
74134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (ImageInfo.Comments[0]) {
74234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        bufLen = addKeyValueString(&buf, bufLen, "UserComment", ImageInfo.Comments);
74334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        if (bufLen == 0) return NULL;
74434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
74534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
74634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    // put the attribute count at the beginnnig of the string
74734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int finalBufLen = strlen(buf) + 20;
74834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    char* finalResult = malloc(finalBufLen);
74934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (finalResult == NULL) {
75034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        free(buf);
75134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return NULL;
75234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
75334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    snprintf(finalResult, finalBufLen, "%d %s", attributeCount, buf);
75434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    int k;
75534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    for (k = 0; k < finalBufLen; k++)
756189fc1d078bf9bb74fa74645b6d6c4e3b58da001Dongwon Kang        if (!isascii(finalResult[k]))
75734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            finalResult[k] = '?';
75834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    free(buf);
75934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
76034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG
7617a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block    ALOGE("*********Returning result \"%s\"", finalResult);
76234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif
76334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jstring result = ((*env)->NewStringUTF(env, finalResult));
76434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    free(finalResult);
76534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    DiscardData();
76634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return result;
76734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
76834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
769db940f2a0ed054ea4d3f39e823220ecf1b15f64crepo syncstatic const char *classPathName = "android/media/ExifInterface";
77034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
77134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic JNINativeMethod methods[] = {
77234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project  {"saveAttributesNative", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)saveAttributes },
77334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project  {"getAttributesNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getAttributes },
77434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project  {"appendThumbnailNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)appendThumbnail },
77534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project  {"commitChangesNative", "(Ljava/lang/String;)V", (void*)commitChanges },
77634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project  {"getThumbnailNative", "(Ljava/lang/String;)[B", (void*)getThumbnail },
77731b17e69a87e4caa50f9c6b1a47c84ef75f79d83Jeff Sharkey  {"getThumbnailRangeNative", "(Ljava/lang/String;)[J", (void*)getThumbnailRange },
77834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project};
77934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
78034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/*
78134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register several native methods for one class.
78234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */
78334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNativeMethods(JNIEnv* env, const char* className,
78434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    JNINativeMethod* gMethods, int numMethods)
78534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
78634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jclass clazz;
78734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
78834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    clazz = (*env)->FindClass(env, className);
78934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (clazz == NULL) {
79034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        fprintf(stderr,
79134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project            "Native registration unable to find class '%s'\n", className);
79234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return JNI_FALSE;
79334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
79434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
79534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        fprintf(stderr, "RegisterNatives failed for '%s'\n", className);
79634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        return JNI_FALSE;
79734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
79834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
79934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return JNI_TRUE;
80034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
80134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
80234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/*
80334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Register native methods for all classes we know about.
80434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */
80534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int registerNatives(JNIEnv* env)
80634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
80734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return jniRegisterNativeMethods(env, classPathName,
80834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project                                    methods, NELEM(methods));
80934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
81034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
81134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project/*
81234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Set some test stuff up.
81334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *
81434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project * Returns the JNI version on success, -1 on failure.
81534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project */
81634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project__attribute__ ((visibility("default"))) jint JNI_OnLoad(JavaVM* vm, void* reserved)
81734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{
81834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    JNIEnv* env = NULL;
81934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    jint result = -1;
82034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
82134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
82234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        fprintf(stderr, "ERROR: GetEnv failed\n");
82334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        goto bail;
82434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
82534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    assert(env != NULL);
82634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
82734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    printf("In mgmain JNI_OnLoad\n");
82834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
82934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    if (registerNatives(env) < 0) {
83034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        fprintf(stderr, "ERROR: Exif native registration failed\n");
83134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project        goto bail;
83234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    }
83334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
83434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    /* success -- return valid version number */
83534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    result = JNI_VERSION_1_4;
83634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project
83734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectbail:
83834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project    return result;
83934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}
840