bool MediaScannerClient::addStringTag(const char* name, const char* value)
{
    if (mLocaleEncoding != kEncodingNone) {
        // don't bother caching strings that are all ASCII.
        // call handleStringTag directly instead.
        // check to see if value (which should be utf8) has any non-ASCII characters
        bool nonAscii = false;
        const char* chp = value;
        char ch;
        while ((ch = *chp++)) {
            if (ch & 0x80) {
                nonAscii = true;
                break;
            }
        }

        if (nonAscii) {
            // save the strings for later so they can be used for native encoding detection
            mNames->push_back(name);
            mValues->push_back(value);
            return true;
        }
        // else fall through
    }

    // autodetection is not necessary, so no need to cache the values
    // pass directly to the client instead
    return handleStringTag(name, value);
}
status_t MediaScannerClient::addStringTag(const char* name, const char* value)
{
    handleStringTag(name, value);
#ifdef MTK_AOSP_ENHANCEMENT
    ALOGI("MediaScannerClient handleStringTag. \n");   
#endif 
    return OK;
}
void MediaScannerClient::endFile()
{
#ifndef ANDROID_DEFAULT_CODE   
   ALOGV("endFile mLocaleEncoding:%d \n",mLocaleEncoding);   
    {      
#else
    if (mLocaleEncoding != kEncodingNone) {
#endif         
        int size = mNames->size();
        uint32_t encoding = kEncodingAll;

#ifndef ANDROID_DEFAULT_CODE   
        
        ALOGV("endFile +possibleEncodings size: %d \n",size);     
        //// compute a bit mask containing all possible encodings
        for (int i = 0; i < mNames->size(); i++)
        { 
        	char const*s=mValues->getEntry(i);
		//	if((s[0]==0xFF)|(!ISUTF8(s))){
            encoding = possibleEncodings(s);
            ALOGD("endFile +possibleEncodings: %d \n",encoding);    
			if(!(encoding==0xFFFFFFFF))
            convertValues(encoding,i);
		//}
			
        }

#else
        // compute a bit mask containing all possible encodings
        for (int i = 0; i < mNames->size(); i++)
            encoding &= possibleEncodings(mValues->getEntry(i));

        // if the locale encoding matches, then assume we have a native encoding.
        if (encoding & mLocaleEncoding)
            convertValues(mLocaleEncoding);
#endif

        // finally, push all name/value pairs to the client
        for (int i = 0; i < mNames->size(); i++) {
            status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
            if (status) {
                break;
            }
        }
    }
    // else addStringTag() has done all the work so we have nothing to do

    delete mNames;
    delete mValues;
    mNames = NULL;
    mValues = NULL;
}

}  // namespace android
void MediaScannerClient::endFile()
{
    if (mLocaleEncoding != kEncodingNone) {
        int size = mNames->size();

        // if the locale encoding matches, then assume we have a native encoding.
		convertValues(mLocaleEncoding);

        // finally, push all name/value pairs to the client
        for (int i = 0; i < mNames->size(); i++) {
            if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
                break;
        }
    }
    // else addStringTag() has done all the work so we have nothing to do

    delete mNames;
    delete mValues;
    mNames = NULL;
    mValues = NULL;
}
status_t MediaScannerClient::addStringTag(const char* name, const char* value)
{
#ifndef ANDROID_DEFAULT_CODE
   ALOGV("addStringTag mLocaleEncoding:%x \n",mLocaleEncoding);

   // validate to make sure it is legal utf8
   uint32_t valid_chars;
//   if (oscl_str_is_valid_utf8((const uint8 *)value, valid_chars))
   {   
//       if (mLocaleEncoding != kEncodingNone)
    { 
#else
    if (mLocaleEncoding != kEncodingNone) {
#endif 
       
        // don't bother caching strings that are all ASCII.
        // call handleStringTag directly instead.
        // check to see if value (which should be utf8) has any non-ASCII characters
#ifndef ANDROID_DEFAULT_CODE
           ALOGV("addStringTag 1 name:%s, value:%s \n",name,value);
#endif
        bool nonAscii = false;
        const char* chp = value;
        char ch;
        while ((ch = *chp++)) {
            if (ch & 0x80) {
                nonAscii = true;
                break;
            }
        }

        if (nonAscii) {
#ifndef ANDROID_DEFAULT_CODE
              ALOGV("addStringTag nonAscii \n"); 
#endif           
            // save the strings for later so they can be used for native encoding detection
            mNames->push_back(name);
            mValues->push_back(value);
            return OK;
        }
        // else fall through
    }

    // autodetection is not necessary, so no need to cache the values
    // pass directly to the client instead
#ifndef ANDROID_DEFAULT_CODE
       ALOGV("+handleStringTag \n");
#endif
    return handleStringTag(name, value);
}
#ifndef ANDROID_DEFAULT_CODE
/*          
   else
   {
      ALOGD( "value '%s' is not a legal UTF8 string\n",value );
      return true;
   } 
*/   

}
#endif


#ifndef ANDROID_DEFAULT_CODE
bool charMatchISO8859(uint8_t ch)
{
	if(((ch > 0x00 && ch < 0x1F)) || (ch == 0x7F) || ((ch > 0x80) && (ch < 0x9F)) )
		return false;
	return true;

}
#endif


#ifndef ANDROID_DEFAULT_CODE
//code page of sight words in GBK,added by xu lai
static const CharRange kGBKSWRanges[] = {
    { 0xB0A1, 0xB0FE },
    { 0xB1A1, 0xB1FE },
    { 0xB2A1, 0xB2FE },
    { 0xB3A1, 0xB3FE },
    { 0xB4A1, 0xB4FE },
    { 0xB5A1, 0xB5FE },
    { 0xB6A1, 0xB6FE },
    { 0xB7A1, 0xB7FE }, 
    { 0xB8A1, 0xB8FE },
    { 0xB9A1, 0xB9FE },
    { 0xBAA1, 0xBAFE },
    { 0xBBA1, 0xBBFE },
    { 0xBCA1, 0xBCFE },
    { 0xBDA1, 0xBDFE },
    { 0xBEA1, 0xBEFE }, 
    { 0xBFA1, 0xBFFE },
    
    { 0xC0A1, 0xC0FE },
    { 0xC1A1, 0xC1FE },
    { 0xC2A1, 0xC2FE },
    { 0xC3A1, 0xC3FE },
    { 0xC4A1, 0xC4FE },
    { 0xC5A1, 0xC5FE },
    { 0xC6A1, 0xC6FE },
    { 0xC7A1, 0xC7FE }, 
    { 0xC8A1, 0xC8FE },
    { 0xC9A1, 0xC9FE },
    { 0xCAA1, 0xCAFE },
    { 0xCBA1, 0xCBFE },
    { 0xCCA1, 0xCCFE },
    { 0xCDA1, 0xCDFE },
    { 0xCEA1, 0xCEFE }, 
    { 0xCFA1, 0xCFFE },
    
    { 0xD0A1, 0xD0FE },
    { 0xD1A1, 0xD1FE },
    { 0xD2A1, 0xD2FE },
    { 0xD3A1, 0xD3FE },
    { 0xD4A1, 0xD4FE },
    { 0xD5A1, 0xD5FE },
    { 0xD6A1, 0xD6FE },
    { 0xD7A1, 0xD7FE }, 
    { 0xD8A1, 0xD8FE },
    { 0xD9A1, 0xD9FE },
    { 0xDAA1, 0xDAFE },
    { 0xDBA1, 0xDBFE },
    { 0xDCA1, 0xDCFE },
    { 0xDDA1, 0xDDFE },
    { 0xDEA1, 0xDEFE }, 
    { 0xDFA1, 0xDFFE },
    
    { 0xE0A1, 0xE0FE },
    { 0xE1A1, 0xE1FE },
    { 0xE2A1, 0xE2FE },
    { 0xE3A1, 0xE3FE },
    { 0xE4A1, 0xE4FE },
    { 0xE5A1, 0xE5FE },
    { 0xE6A1, 0xE6FE },
    { 0xE7A1, 0xE7FE }, 
    { 0xE8A1, 0xE8FE },
    { 0xE9A1, 0xE9FE },
    { 0xEAA1, 0xEAFE },
    { 0xEBA1, 0xEBFE },
    { 0xECA1, 0xECFE },
    { 0xEDA1, 0xEDFE },
    { 0xEEA1, 0xEEFE }, 
    { 0xEFA1, 0xEFFE },
    
    { 0xF0A1, 0xF0FE },
    { 0xF1A1, 0xF1FE },
    { 0xF2A1, 0xF2FE },
    { 0xF3A1, 0xF3FE },
    { 0xF4A1, 0xF4FE },
    { 0xF5A1, 0xF5FE },
    { 0xF6A1, 0xF6FE },
    { 0xF7A1, 0xF7FE }, 
        
};

//code page of sight words in BIG5,added by xu lai
static const CharRange kBig5SWRanges[] = {
    { 0xA440, 0xA47E },
    { 0xA4A1, 0xA4FE },
    { 0xA540, 0xA57E },
    { 0xA5A1, 0xA5FE },
    { 0xA640, 0xA67E },
    { 0xA6A1, 0xA6FE },
    { 0xA740, 0xA77E },
    { 0xA7A1, 0xA7FE },
    { 0xA840, 0xA87E },
    { 0xA8A1, 0xA8FE },
    { 0xA940, 0xA97E },
    { 0xA9A1, 0xA9FE },
    { 0xAA40, 0xAA7E },
    { 0xAAA1, 0xAAFE },
    { 0xAB40, 0xAB7E },
    { 0xABA1, 0xABFE },
    { 0xAC40, 0xAC7E },
    { 0xACA1, 0xACFE },
    { 0xAD40, 0xAD7E },
    { 0xADA1, 0xADFE },
    { 0xAE40, 0xAE7E },
    { 0xAEA1, 0xAEFE },
    { 0xAF40, 0xAF7E },
    { 0xAFA1, 0xAFFE },
    { 0xB040, 0xB07E },
    { 0xB0A1, 0xB0FE },
    { 0xB140, 0xB17E },
    { 0xB1A1, 0xB1FE },
    { 0xB240, 0xB27E },
    { 0xB2A1, 0xB2FE },
    { 0xB340, 0xB37E },
    { 0xB3A1, 0xB3FE },
    { 0xB440, 0xB47E },
    { 0xB4A1, 0xB4FE },
    { 0xB540, 0xB57E },
    { 0xB5A1, 0xB5FE },
    { 0xB640, 0xB67E },
    { 0xB6A1, 0xB6FE },
    { 0xB740, 0xB77E },
    { 0xB7A1, 0xB7FE },
    { 0xB840, 0xB87E },
    { 0xB8A1, 0xB8FE },
    { 0xB940, 0xB97E },
    { 0xB9A1, 0xB9FE },
    { 0xBA40, 0xBA7E },
    { 0xBAA1, 0xBAFE },
    { 0xBB40, 0xBB7E },
    { 0xBBA1, 0xBBFE },
    { 0xBC40, 0xBC7E },
    { 0xBCA1, 0xBCFE },
    { 0xBD40, 0xBD7E },
    { 0xBDA1, 0xBDFE },
    { 0xBE40, 0xBE7E },
    { 0xBEA1, 0xBEFE },
    { 0xBF40, 0xBF7E },
    { 0xBFA1, 0xBFFE },
    { 0xC040, 0xC07E },
    { 0xC0A1, 0xC0FE },
    { 0xC140, 0xC17E },
    { 0xC1A1, 0xC1FE },
    { 0xC240, 0xC27E },
    { 0xC2A1, 0xC2FE },
    { 0xC340, 0xC37E },
    { 0xC3A1, 0xC3FE },
    { 0xC440, 0xC47E },
    { 0xC4A1, 0xC4FE },
    { 0xC540, 0xC57E },
    { 0xC5A1, 0xC5FE },
    { 0xC640, 0xC67E },   
};

#define ARRAY_SIZE(x)   (sizeof(x) / sizeof(*x))
static bool charMatchestest(int ch, const CharRange* encodingRanges, int rangeCount) {
    // Use binary search to see if the character is contained in the encoding
    int low = 0;
    int high = rangeCount;

    while (low < high) {
        int i = (low + high) / 2;
        const CharRange* range = &encodingRanges[i];
        if (ch >= range->first && ch <= range->last)
            return true;
        if (ch > range->last)
            low = i + 1;
        else
            high = i;
    }

    return false;
}