MediaScannerClient.cpp revision 1f7d356fa094b975ad2ebf9217be6abba2c70825
1413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber/*
2413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * Copyright (C) 2009 The Android Open Source Project
3413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber *
4413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * you may not use this file except in compliance with the License.
6413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * You may obtain a copy of the License at
7413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber *
8413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber *
10413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * Unless required by applicable law or agreed to in writing, software
11413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * See the License for the specific language governing permissions and
14413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber * limitations under the License.
15413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber */
16413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
17413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber#include <media/mediascanner.h>
18413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
191f7d356fa094b975ad2ebf9217be6abba2c70825Mathias Agopian#include "StringArray.h"
20413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
21413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber#include "autodetect.h"
22413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber#include "unicode/ucnv.h"
23413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber#include "unicode/ustring.h"
24413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
25413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Hubernamespace android {
26413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
27413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas HuberMediaScannerClient::MediaScannerClient()
28413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    :   mNames(NULL),
29413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        mValues(NULL),
30413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        mLocaleEncoding(kEncodingNone)
31413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
32413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
33413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
34413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas HuberMediaScannerClient::~MediaScannerClient()
35413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
36413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    delete mNames;
37413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    delete mValues;
38413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
39413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
40413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Hubervoid MediaScannerClient::setLocale(const char* locale)
41413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
42413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    if (!locale) return;
43413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
44413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    if (!strncmp(locale, "ja", 2))
45413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        mLocaleEncoding = kEncodingShiftJIS;
46413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    else if (!strncmp(locale, "ko", 2))
47413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        mLocaleEncoding = kEncodingEUCKR;
48413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    else if (!strncmp(locale, "zh", 2)) {
49413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        if (!strcmp(locale, "zh_CN")) {
50413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // simplified chinese for mainland China
51413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            mLocaleEncoding = kEncodingGBK;
52413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        } else {
53413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // assume traditional for non-mainland Chinese locales (Taiwan, Hong Kong, Singapore)
54413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            mLocaleEncoding = kEncodingBig5;
55413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
56413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
57413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
58413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
59413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Hubervoid MediaScannerClient::beginFile()
60413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
61413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    mNames = new StringArray;
62413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    mValues = new StringArray;
63413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
64413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
657188e55f54a43c55fd6b96454720c447f1dc454eJeff Brownstatus_t MediaScannerClient::addStringTag(const char* name, const char* value)
66413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
67b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen    if (mLocaleEncoding != kEncodingNone) {
68b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // don't bother caching strings that are all ASCII.
69b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // call handleStringTag directly instead.
70b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // check to see if value (which should be utf8) has any non-ASCII characters
71b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        bool nonAscii = false;
72b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        const char* chp = value;
73b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        char ch;
74b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        while ((ch = *chp++)) {
75b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            if (ch & 0x80) {
76b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen                nonAscii = true;
77b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen                break;
78b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            }
79413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
80413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
81b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        if (nonAscii) {
82b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            // save the strings for later so they can be used for native encoding detection
83b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            mNames->push_back(name);
84b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            mValues->push_back(value);
85153cefdf4acab25355f590d7760ebf73ef6096a9Marco Nelissen            return OK;
86b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        }
87b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // else fall through
88413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
89413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
90413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    // autodetection is not necessary, so no need to cache the values
91413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    // pass directly to the client instead
92413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    return handleStringTag(name, value);
93413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
94413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
95413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huberstatic uint32_t possibleEncodings(const char* s)
96413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
97413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    uint32_t result = kEncodingAll;
98413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    // if s contains a native encoding, then it was mistakenly encoded in utf8 as if it were latin-1
99413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    // so we need to reverse the latin-1 -> utf8 conversion to get the native chars back
100413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    uint8_t ch1, ch2;
101413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    uint8_t* chp = (uint8_t *)s;
102413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
103413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    while ((ch1 = *chp++)) {
104413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        if (ch1 & 0x80) {
105413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            ch2 = *chp++;
106413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            ch1 = ((ch1 << 6) & 0xC0) | (ch2 & 0x3F);
107413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // ch1 is now the first byte of the potential native char
108413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
109413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            ch2 = *chp++;
110413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            if (ch2 & 0x80)
111413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                ch2 = ((ch2 << 6) & 0xC0) | (*chp++ & 0x3F);
112413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // ch2 is now the second byte of the potential native char
113413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            int ch = (int)ch1 << 8 | (int)ch2;
114413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            result &= findPossibleEncodings(ch);
115413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
116413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        // else ASCII character, which could be anything
117413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
118413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
119413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    return result;
120413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
121413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
122413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Hubervoid MediaScannerClient::convertValues(uint32_t encoding)
123413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
124413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    const char* enc = NULL;
125413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    switch (encoding) {
126413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        case kEncodingShiftJIS:
127413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            enc = "shift-jis";
128413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            break;
129413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        case kEncodingGBK:
130413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            enc = "gbk";
131413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            break;
132413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        case kEncodingBig5:
133413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            enc = "Big5";
134413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            break;
135413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        case kEncodingEUCKR:
136413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            enc = "EUC-KR";
137413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            break;
138413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
139413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
140413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    if (enc) {
141413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        UErrorCode status = U_ZERO_ERROR;
142413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
143413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        UConverter *conv = ucnv_open(enc, &status);
144413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        if (U_FAILURE(status)) {
14590bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten            ALOGE("could not create UConverter for %s", enc);
146413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            return;
147413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
148413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        UConverter *utf8Conv = ucnv_open("UTF-8", &status);
149413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        if (U_FAILURE(status)) {
15090bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten            ALOGE("could not create UConverter for UTF-8");
151413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            ucnv_close(conv);
152413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            return;
153413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
154413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
155413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        // for each value string, convert from native encoding to UTF-8
156413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        for (int i = 0; i < mNames->size(); i++) {
157413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // first we need to untangle the utf8 and convert it back to the original bytes
158413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // since we are reducing the length of the string, we can do this in place
159413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            uint8_t* src = (uint8_t *)mValues->getEntry(i);
160413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            int len = strlen((char *)src);
161413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            uint8_t* dest = src;
162413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
163413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            uint8_t uch;
164413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            while ((uch = *src++)) {
165413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                if (uch & 0x80)
166413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                    *dest++ = ((uch << 6) & 0xC0) | (*src++ & 0x3F);
167413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                else
168413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                    *dest++ = uch;
169413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            }
170413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            *dest = 0;
171413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
172413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            // now convert from native encoding to UTF-8
173413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            const char* source = mValues->getEntry(i);
174413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            int targetLength = len * 3 + 1;
175413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            char* buffer = new char[targetLength];
17683bc7f3cf78b28a818417f40a4f0c00593993366Glenn Kasten            // don't normally check for NULL, but in this case targetLength may be large
177413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            if (!buffer)
178413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                break;
179413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            char* target = buffer;
180413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
181413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            ucnv_convertEx(utf8Conv, conv, &target, target + targetLength,
182413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                    &source, (const char *)dest, NULL, NULL, NULL, NULL, TRUE, TRUE, &status);
183413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            if (U_FAILURE(status)) {
18490bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten                ALOGE("ucnv_convertEx failed: %d", status);
185413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                mValues->setEntry(i, "???");
186413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            } else {
187413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                // zero terminate
188413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                *target = 0;
189413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber                mValues->setEntry(i, buffer);
190413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            }
191413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
192413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber            delete[] buffer;
193413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        }
194413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
195413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        ucnv_close(conv);
196413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber        ucnv_close(utf8Conv);
197413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
198413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
199413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
200413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Hubervoid MediaScannerClient::endFile()
201413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber{
202b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen    if (mLocaleEncoding != kEncodingNone) {
203b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        int size = mNames->size();
204b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        uint32_t encoding = kEncodingAll;
205413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
206b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // compute a bit mask containing all possible encodings
207b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        for (int i = 0; i < mNames->size(); i++)
208b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            encoding &= possibleEncodings(mValues->getEntry(i));
209b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen
210b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // if the locale encoding matches, then assume we have a native encoding.
211b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        if (encoding & mLocaleEncoding)
212b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen            convertValues(mLocaleEncoding);
213b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen
214b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        // finally, push all name/value pairs to the client
215b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        for (int i = 0; i < mNames->size(); i++) {
2167188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown            status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
2177188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown            if (status) {
218b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen                break;
2197188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown            }
220b5c3107262fdf82aef4bd5ee8b8c60dd3e4725feMarco Nelissen        }
221413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    }
222413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    // else addStringTag() has done all the work so we have nothing to do
223413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
224413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    delete mNames;
225413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    delete mValues;
226413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    mNames = NULL;
227413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber    mValues = NULL;
228413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}
229413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber
230413f523afe96aff02d2b0a7459127b8f67b2b43cAndreas Huber}  // namespace android
231