OSDN Git Service

ABIPicker: match package name by patterns
[android-x86/frameworks-base.git] / core / jni / abipicker / ABIPicker.cpp
1 #define LOG_TAG "ABIPicker"
2
3 #include "abipicker/ABIPicker.h"
4 #include "abipicker/ELFLite.h"
5
6 #include <androidfw/ZipFileRO.h>
7 #include <androidfw/ZipUtils.h>
8 #include <fnmatch.h>
9
10 namespace android {
11 #define ARR_SIZE(x)     (sizeof(x)/sizeof(x[0]))
12
13 #define SO_NAME_MAX (4096)
14
15 #define IMPOSSIBLE_LIB_NAME    "/mixed/"
16 #define IMPOSSIBLE_LIB_LEN  (sizeof(IMPOSSIBLE_LIB_NAME)-1)
17
18 #define ARMABI      "armeabi"
19 #define ARMV7ABI    "armeabi-v7a"
20 #define ARM64ABI    "arm64-v8a"
21 #define X86ABI      "x86"
22 #define X8664ABI    "x86_64"
23
24 #define APK_LIB "lib/"
25 #define APK_LIB_LEN (sizeof(APK_LIB) - 1)
26 //#define PICK_LOGGER //flag to debug
27 #ifdef PICK_LOGGER
28 #define P_LOG(...) ALOGI(__VA_ARGS__)
29 #else
30 #define P_LOG(...)
31 #endif
32
33 #define LISTPATH    "/vendor/etc/misc/"
34 #define OEMWHITE    LISTPATH ".OEMWhiteList"
35 #define OEMBLACK    LISTPATH ".OEMBlackList"
36 #define THIRDPARTY  LISTPATH ".ThirdPartySO"
37
38 // load once, hold until poweroff
39 static Vector <char*> thirdPartySO;
40 static Vector <char*> cfgWhite;
41 static Vector <char*> cfgBlack;
42 static bool thirdload = false;
43 static bool whiteload = false;
44 static bool blackload = false;
45
46 static const char* iaRelated[] = {"intel", "intl", "atom", "x86", "x64"};
47
48 void freeAllString(Vector<char*>& list) {
49     Vector<char*>::iterator it = list.begin();
50     while (it != list.end()) {
51         if (*it != NULL) {
52            P_LOG("freeAllSring  %p , %s", it, *it);
53            free(*it);
54            *it = NULL;
55         }
56         it++;
57     }
58 }
59
60 void getConfig(const char* cfgFile , Vector<char*>& cfgVec) {
61     int read = -1;
62     char *line = NULL;
63     size_t len = 0;
64
65     FILE* fp = fopen(cfgFile, "r");
66     if (fp == NULL) {
67         return;
68     }
69
70     freeAllString(cfgVec);
71     cfgVec.clear();
72
73     while ((read = getline(&line, &len, fp)) != -1) {
74         int i = 0 , j = 0;
75         char *cfgline = (char*)malloc(len);
76         if (cfgline == NULL) {
77            P_LOG("malloc error");
78            break;
79         }
80         for (i = 0; i < read; i++) {
81            if (!isspace(line[i])) {
82               cfgline[j++] = line[i];
83            }
84         }
85         cfgline[j] = '\0';
86         cfgVec.push_back(cfgline);
87         P_LOG("orignal %s , vec: %s ", line, cfgline);
88     }
89     free(line);
90     fclose(fp);
91 }
92
93 bool isInOEMWhiteList(const char* pkgName) {
94     bool result = false;
95     if (pkgName == NULL) {
96         return result;
97     }
98
99     if (!whiteload) {
100        getConfig(OEMWHITE, cfgWhite);
101        whiteload = true;
102     }
103
104     Vector<char*>::iterator it = cfgWhite.begin();
105     for (; it != cfgWhite.end(); it++) {
106        P_LOG("whitelist : %s", *it);
107        if (0 == fnmatch(*it, pkgName, 0)) {
108           ALOGI("whitelist %s by %s", pkgName, *it);
109           result = true;
110           break;
111        }
112     }
113     return result;
114 }
115
116 bool isInOEMBlackList(const char* pkgName) {
117     bool result = false;
118     if (pkgName == NULL) {
119         return result;
120     }
121
122     if (!blackload) {
123        getConfig(OEMBLACK,  cfgBlack);
124        blackload = true;
125     }
126
127     Vector<char*>::iterator it = cfgBlack.begin();
128     for (; it != cfgBlack.end(); it++) {
129        if (0 == fnmatch(*it, pkgName, 0)) {
130           ALOGI("blacklist %s by %s", pkgName, *it);
131           result = true;
132           break;
133        }
134     }
135     return result;
136 }
137
138 bool isReliableLib(Vector<char*>& libList) {
139     unsigned sz = libList.size();
140     int len = ARR_SIZE(iaRelated);
141     for (unsigned i = 0; i < sz; i++) {
142         for (int j=0; j < len; j++) {
143             char* p = NULL;
144             if (NULL != (p = strcasestr(libList[i], iaRelated[j]))) {
145                 int lenIA = strlen(iaRelated[j]);
146                 if (!isalpha(*(p+lenIA))) {
147                     if (!isalpha(*(p-1)) || (p == (libList[i] + 3))) {
148                         return true;
149                     }
150                 }
151             }
152         }
153     }
154
155     return false;
156 }
157
158 static bool isValidELF(char* buffer) {
159     if (buffer[EI_MAG0] != ELFMAG0 &&
160         buffer[EI_MAG1] != ELFMAG1 &&
161         buffer[EI_MAG2] != ELFMAG2 &&
162         buffer[EI_MAG3] != ELFMAG3) {
163         return false;
164     }
165     return true;
166 }
167
168 // assume that x86 has the only machine-code 3, and x86_64 62
169 static bool isMixedLib(char* libCur, char* buffer) {
170     bool isX86_64 = (0 == strcmp(libCur, X8664ABI)) ? true: false;
171     uint16_t machine_code = *((uint16_t*)(&buffer[ELF_MACHINE_OFFSET]));
172     bool mixed = false;
173     if (isX86_64) {
174         if (machine_code != EM_X86_64) {
175             mixed = true;
176         }
177     } else {
178         if (machine_code != EM_386) {
179             mixed = true;
180         }
181     }
182     return mixed;
183 }
184
185 // compare the given string with the length, igonre upper and lower
186 // len must be less than the length of two string
187 static bool ignoreCmp(const char* str1, const char* str2, int len){
188     assert (str1 != NULL && str2 != NULL);
189     assert ((len <= strlen(str1)) && (len <= strlen(str2)));
190     for (int i = 0 ; i < len; i++) {
191         if (str1[i] != str2[i]) {
192             if(isalpha(str1[i]) && isalpha(str2[i])
193                     && (abs((str1[i]-str2[i])) == 32)) {
194                 continue;
195             }
196             return false;
197         }
198     }
199     return true;
200 }
201
202 static bool isInThirdPartySOList(char* libName) {
203     assert (libName != NULL);
204     size_t libLen = strlen(libName);
205     size_t sz = thirdPartySO.size();
206     for (size_t i = 0; i < sz; i++) {
207         // thirdPartySO[i] won't be NULL
208         assert(thirdPartySO[i] != NULL);
209         size_t n = strlen(thirdPartySO[i]);
210         // three char for ".so"
211         int j = libLen - 4;
212         // now only '-' '-' and '.'found
213         while((j >= 0) && (isdigit(libName[j]) || (libName[j] == '-')
214               || (libName[j] == '_') || (libName[j] == '.'))) {
215             j--;
216         }
217         // three char for "lib" and include the name with no letters
218         if ((j == 2) || ((size_t)j == (n+2))) {
219             if (ignoreCmp(libName+3, thirdPartySO[i], n)) {
220                 P_LOG("ABIpicker libName %s,In Third", libName);
221                 return true;
222             }
223         }
224
225     }
226     return false;
227 }
228
229 static void insertionSort(Vector<char*>& list) {
230     P_LOG("in insertionSort, list size = %d\n", list.size());
231
232     for (size_t i = 1; i < list.size(); i++) {
233         int j = i - 1;
234         char* x = list[i];
235         P_LOG("sort 1. x=%s, i=%d, j=%d\n", x, i, j);
236         while (j >= 0 && (strcmp(list[j], x) > 0)) {
237             list.replaceAt(list[j], j + 1);
238             j--;
239         }
240         list.replaceAt(x, j + 1);
241     }
242 }
243
244 // Use armRef as a reference, compare all libraries of iaRef with all
245 // libraries of armRef.If the two are match or iaRef is more, iaRef
246 // will be returned with *result and true is return value. Or else,
247 // *result is rawResult and false is return value
248 bool ABIPicker::compare(char* armRef, char* iaRef,
249                         char* rawResult, char** result) {
250     bool ret = true;
251     *result = rawResult;
252
253     do {
254         assert(armRef != NULL);
255         if (0 == strlen(armRef)) {
256             *result = strlen(iaRef) > 0 ? iaRef : rawResult;
257             ret = strlen(iaRef) > 0 ? true : false;
258             break;
259         }
260         assert(iaRef != NULL);
261         if (0 == strlen(iaRef)) {
262             *result = armRef;
263             ret = false;
264             break;
265         }
266
267         Vector<char*>* iaRefList = getLibList(iaRef);
268         Vector<char*>* armRefList = getLibList(armRef);
269         if (iaRefList == NULL || armRefList == NULL) {
270             break;
271         }
272
273         if (isReliableLib(*iaRefList)) {
274             *result = iaRef;
275             break;
276         }
277
278         if (compareLibList(*iaRefList, *armRefList)) {
279             *result = iaRef;
280             break;
281         }
282
283         size_t iaIsvLibCount = 0;
284         size_t armIsvLibCount = 0;
285         if (!compare3rdPartyLibList(iaRef, armRef,
286                     &iaIsvLibCount, &armIsvLibCount)) {
287             *result = armRef;
288             ret = false;
289             break;
290         }
291
292         if (iaIsvLibCount > 0) {
293             *result = iaRef;
294             break;
295         }
296
297         *result = armRef;
298         ret = false;
299     } while (0);
300
301     ALOGV("%s Vs. %s, return %s\n",
302             iaRef ? iaRef : "NULL",
303             armRef ? armRef : "NULL", *result);
304     return ret;
305 }
306
307 bool ABIPicker::compareLibList(Vector<char*>& iaRefList,
308         Vector<char*>& armRefList) {
309
310     unsigned iaSize = iaRefList.size();
311     unsigned armSize = armRefList.size();
312     if (iaSize < armSize) {
313         return false;
314     } else if (iaSize == 0 && armSize == 0) {
315         return true;
316     }
317
318     int iaNum = 0;
319     int armNum = 0;
320     Vector<char*>::iterator itIa = iaRefList.begin();
321     Vector<char*>::iterator itArm = armRefList.begin();
322     bool isEqual = false;
323     while (itIa != iaRefList.end() && itArm != armRefList.end()) {
324         if ((iaSize-iaNum) < (armSize-armNum)) {
325             return false;
326         }
327         isEqual = false ;
328         char* armLibName = *itArm;
329         int armLen = strlen (armLibName);
330         armNum++;
331
332         while (itIa != iaRefList.end() && !isEqual) {
333             char* iaLibName = *itIa;
334             iaNum++;
335             int iaLen = strlen (iaLibName);
336             if (iaLen == armLen) {
337                 if (ignoreCmp(iaLibName, armLibName, iaLen)) {
338                     isEqual = true;
339                 }
340             }
341             itIa++;
342         }
343         itArm++;
344     }
345     // till the end, and the last result is equal
346     if (itArm == armRefList.end() && isEqual){
347         return true;
348     }
349
350     return false;
351 }
352
353 bool ABIPicker::compare3rdPartyLibList(
354                 char* iaRef, char* armRef,
355                 size_t* iaIsvLibCount, size_t* armIsvLibCount) {
356     bool result = true;
357
358     Vector<char*>* iaRefList = getLibList(iaRef);
359     Vector<char*>* armRefList = getLibList(armRef);
360     if (iaRefList == NULL || armRefList == NULL) {
361         return result;
362     }
363
364     if (!thirdload) {
365         getConfig(THIRDPARTY, thirdPartySO);
366         thirdload = true;
367     }
368
369     Vector<char*>* armRef3rdPartyLibList = new Vector<char*>();
370     Vector<char*>::iterator itArm = armRefList->begin();
371     while (itArm != armRefList->end()) {
372         char* armLibName = *itArm;
373         if (isInThirdPartySOList(armLibName)) {
374             armRef3rdPartyLibList->push_back(armLibName);
375         } else {
376             (*armIsvLibCount)++;
377         }
378
379         itArm++;
380     }
381
382     Vector<char*>::iterator itIa = iaRefList->begin();
383     Vector<char*>* iaRef3rdPartyLibList = new Vector<char*>();
384     while (itIa != iaRefList->end()) {
385         char* iaLibName = *itIa;
386         if (isInThirdPartySOList(iaLibName)) {
387             iaRef3rdPartyLibList->push_back(iaLibName);
388         } else {
389             (*iaIsvLibCount)++;
390         }
391
392         itIa++;
393     }
394     result = compareLibList(*iaRef3rdPartyLibList, *armRef3rdPartyLibList);
395
396     armRef3rdPartyLibList->clear();
397     delete armRef3rdPartyLibList;
398     iaRef3rdPartyLibList->clear();
399     delete iaRef3rdPartyLibList;
400     return result;
401 }
402
403 char* ABIPicker::getAbiName(int abi) {
404     if (abi <  0 || (unsigned)abi >= mLibList->size()) {
405         return NULL;
406     }
407
408     char* ret = NULL;
409     int index = 0;
410     Vector<struct libInfo*>::iterator it = mLibList->begin();
411     while (it != mLibList->end()) {
412         if (index == abi) {
413             ret = (*it)->abiName;
414             break;
415         }
416
417         index++;
418         it++;
419     }
420
421     return ret;
422 }
423
424 int ABIPicker::getAbiIndex(const char* abiName) {
425     int ret = -1;
426
427     int index = 0;
428     Vector<struct libInfo*>::iterator it = mLibList->begin();
429     while (it != mLibList->end()) {
430         if (0 == strcmp(abiName, (*it)->abiName)) {
431             ret = index;
432             break;
433         }
434
435         index++;
436         it++;
437     }
438
439     return ret;
440 }
441
442 Vector<char*>* ABIPicker::getLibList(const char* abiName) {
443     Vector<char*>* ret = NULL;
444     Vector<struct libInfo*>::iterator it = mLibList->begin();
445     while (it != mLibList->end()) {
446         if (0 == strcmp(abiName, (*it)->abiName)) {
447             ret = (*it)->libNameList;
448             break;
449         }
450         it++;
451     }
452     P_LOG("getLibList of %s return %p\n", abiName, ret);
453     return ret;
454 }
455
456
457 bool ABIPicker::isABILibValid(const char* abiName) {
458     Vector<char*>* specificAbiLibList = getLibList(abiName);
459     return ((specificAbiLibList && specificAbiLibList->size()) > 0);
460 }
461
462 bool ABIPicker::foundMixedELF(const char* abiName) {
463     Vector<char*>* libNameList = getLibList(abiName);
464     if (!libNameList) {
465         return false;
466     }
467     if (libNameList->size() == 0) {
468         return false;
469     }
470
471     if (0 != strcasecmp(*(libNameList->begin()), IMPOSSIBLE_LIB_NAME)) {
472         return false;
473     }
474
475     return true;
476 }
477
478 ABIPicker::ABIPicker(const char* pkgName, Vector<ScopedUtfChars*> abiList) {
479     mLibList = new Vector<struct libInfo*>();
480     mpkgName = strdup(pkgName);
481     if (mpkgName == NULL) {
482         P_LOG("ABIPicker Construct Allocated space fails");
483     }
484     Vector<ScopedUtfChars*>::iterator it = abiList.begin();
485     while (it != abiList.end()) {
486         if (!(*it)) {
487             break;
488         }
489
490         struct libInfo* tmp = (struct libInfo*)calloc(1,
491                 sizeof(struct libInfo));
492         if (tmp == NULL) {
493            P_LOG("ABIPicker Construct Allocated space fail %s", (*it)->c_str());
494            break;
495         }
496
497         snprintf(tmp->abiName, (*it)->size() + 1, "%s", (*it)->c_str());
498         tmp->libNameList = new Vector<char*>();
499         P_LOG("ABIPicker Construct %s , libNameList: %p",
500              tmp->abiName, tmp->libNameList);
501         mLibList->push_back(tmp);
502         it++;
503     }
504 }
505
506 ABIPicker::~ABIPicker(void) {
507     free(mpkgName);
508     mpkgName = NULL;
509     Vector<struct libInfo*>::iterator it = mLibList->begin();
510     while (it != mLibList->end()) {
511         freeAllString(*((*it)->libNameList));
512         (*it)->libNameList->clear();
513         delete (*it)->libNameList;
514         (*it)->libNameList = NULL;
515
516         free(*it);
517         *it = NULL;
518         it++;
519     }
520     mLibList->clear();
521     delete mLibList;
522 }
523
524 bool ABIPicker::buildNativeLibList(void* apkHandle) {
525     bool ret = false;
526
527     if (apkHandle == NULL) {
528         ALOGE("apkHandle is NULL\n");
529         return ret;
530     }
531
532     ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
533     void* cookie = NULL;
534     if (!zipFile->startIteration(&cookie)) {
535         ALOGE("apk file is broken\n");
536         return ret;
537     }
538
539     ZipEntryRO next = NULL;
540     char* unCompBuff = NULL;
541     char fileName[SO_NAME_MAX + 1];
542     while ((next = zipFile->nextEntry(cookie))) {
543         if (zipFile->getEntryFileName(next, fileName, SO_NAME_MAX)) {
544             ALOGE("apk file is broken, can not get entry name\n");
545             ret = false;
546             break;
547         }
548         fileName[SO_NAME_MAX] = '\0';
549
550         // Make sure we're in the lib directory of the ZIP.
551         // find out entries with such names: "lib/xxxxxxx" or "lib/"
552         if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
553             continue;
554         }
555
556         // find out any invalid ELF file
557         uint32_t unCompLen = 0;
558         if (!zipFile->getEntryInfo(next, NULL, &unCompLen, NULL, NULL, NULL,
559                                     NULL)) {
560             ALOGE("apk file is broken, can not get entry info\n");
561             ret = false;
562             break;
563         }
564
565         if (unCompLen == 0) {
566             ALOGV("skip a empty file(%s)\n", fileName);
567             continue;
568         }
569
570         free(unCompBuff);
571         unCompBuff = NULL;
572
573         unCompBuff = (char*)malloc(unCompLen);
574         if (unCompBuff == NULL) {
575             ALOGE("malloc failed size %d\n", unCompLen);
576             ret = false;
577             break;
578         }
579         memset(unCompBuff, 0, unCompLen);
580         // THE MOST TIME COST OPERATION
581         if (!zipFile->uncompressEntry(next, unCompBuff, unCompLen)) {
582             ALOGE("%s: uncompress failed\n", fileName);
583             ret = false;
584             break;
585         }
586
587         if (!isValidELF(unCompBuff)) {
588             ALOGI("skip a fake .ELF file(%s)\n", fileName);
589             continue;
590         }
591
592         // It is a real .so file, prepare to record
593         // find abi name and focus on what we care: arm(s) and x86(s)
594         // at least lastSlash points to the end of "lib/"
595         const char* lastSlash = strrchr(fileName, '/');
596         const char* cpuAbiOffset = fileName + APK_LIB_LEN;
597         // just in case if fileName is in an abnormal format, like lib/libname,
598         // lib//libname
599         if (lastSlash <= cpuAbiOffset) {
600             ALOGI("skip a invalid lib file(%s)\n", fileName);
601             continue;
602         }
603
604         const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
605         char curAbiName[ABI_NAME_MAX_LENGTH];
606         if (cpuAbiRegionSize >= ABI_NAME_MAX_LENGTH) {
607             continue;
608         }
609         snprintf(curAbiName, cpuAbiRegionSize + 1, "%s", cpuAbiOffset);
610
611         Vector<char*>* libListOfCurAbi = getLibList(curAbiName);
612         if (!libListOfCurAbi) {
613             P_LOG("getLibList of %s return NULL\n", curAbiName);
614             continue;
615         }
616
617         // mixed arm elf in lib/x86 or lib/x86_64
618         // but we don't consider a compareable scenario in lib/arm*
619         if (0 == strcmp(curAbiName, X86ABI) ||
620                 0 == strcmp(curAbiName, X8664ABI)) {
621             if (!libListOfCurAbi->empty()) {
622                 char* firstElement = libListOfCurAbi->itemAt(0);
623                 if (0 == strcmp(firstElement, IMPOSSIBLE_LIB_NAME)) {
624                     // won't add any new into the list if found mixed
625                     // lib before
626                     P_LOG("won't count count if found mixed lib before");
627                     continue;
628                 }
629             }
630
631             if (isMixedLib(curAbiName, unCompBuff)) {
632                 P_LOG("found mixed lib(%s) in lib/%s/", curAbiName, fileName);
633                 freeAllString(*libListOfCurAbi);
634                 libListOfCurAbi->clear();
635                 char* mixedLib = (char*)malloc(IMPOSSIBLE_LIB_LEN+1);
636                 if (!mixedLib) {
637                     ALOGE("malloc failed size %zu", IMPOSSIBLE_LIB_LEN + 1);
638                     ret = false;
639                     break;
640                 }
641                 snprintf(mixedLib, (IMPOSSIBLE_LIB_LEN+1), "%s", IMPOSSIBLE_LIB_NAME);
642                 mixedLib[IMPOSSIBLE_LIB_LEN] ='\0';
643                 libListOfCurAbi->push_back(mixedLib);
644                 continue;
645             }
646         }
647
648         // now, lastSlash should point to lib name
649         lastSlash++;
650         const size_t libNameSize = strlen(lastSlash);
651         char* curLibName = (char*)malloc(libNameSize+1);
652         if (!curLibName) {
653             ALOGE("malloc failed size %zu\n", libNameSize+1);
654             ret = false;
655             break;
656         }
657         snprintf(curLibName,libNameSize+1, "%s", lastSlash);
658         curLibName[libNameSize] = '\0';
659
660         libListOfCurAbi->push_back(curLibName);
661
662         ret = true;
663     }
664
665     free(unCompBuff);
666     unCompBuff = NULL;
667
668     zipFile->endIteration(cookie);
669
670     for (unsigned i = 0; i < mLibList->size(); i++) {
671         struct libInfo* tmp = mLibList->itemAt(i);
672         insertionSort(*(tmp->libNameList));
673     }
674     return ret;
675 }
676
677 int ABIPicker::pickupRightABI(int sysPrefer) {
678     char* sysPreferAbiName = getAbiName(sysPrefer);
679     if (!sysPreferAbiName) {
680         return sysPrefer;
681     }
682
683     bool is64BitPrefer = (0 == strcmp(sysPreferAbiName, X8664ABI));
684     bool x8664HasMixedELF = foundMixedELF(X8664ABI);
685     bool x86HasMixedELF = foundMixedELF(X86ABI);
686
687     bool armv7LibValid = isABILibValid(ARMV7ABI);
688     bool armv5LibValid = isABILibValid(ARMABI);
689     bool armv8LibValid = isABILibValid(ARM64ABI);
690     bool x86LibValid = x86HasMixedELF ? 0 : isABILibValid(X86ABI);
691     bool x8664LibValid = x8664HasMixedELF ? 0 : isABILibValid(X8664ABI);
692
693     // in OEMBlackList, need to be supported by bt
694     // but in case of armlib doesn't exist, we choose x86 or x86_64
695     if (isInOEMBlackList(mpkgName)) {
696         if (armv7LibValid) {
697             return getAbiIndex(ARMV7ABI);
698         } else if (armv5LibValid) {
699             return getAbiIndex(ARMABI);
700         } else if (armv8LibValid) {
701             return getAbiIndex(ARM64ABI);
702         }
703     }
704
705     char arm64Ref[ABI_NAME_MAX_LENGTH];
706     if (armv8LibValid) {
707         snprintf(arm64Ref, sizeof(ARM64ABI), "%s", ARM64ABI);
708     } else {
709         arm64Ref[0] = '\0';
710     }
711
712     char arm32Ref[ABI_NAME_MAX_LENGTH];
713     if (armv7LibValid) {
714         snprintf(arm32Ref, sizeof(ARMV7ABI), "%s", ARMV7ABI);
715     } else if (armv5LibValid) {
716         snprintf(arm32Ref, sizeof(ARMABI), "%s", ARMABI);
717     } else {
718         arm32Ref[0] = '\0';
719     }
720
721     char ia32Ref[ABI_NAME_MAX_LENGTH];
722     if (x86LibValid) {
723         snprintf(ia32Ref, sizeof(X86ABI), "%s", X86ABI);
724     } else {
725         ia32Ref[0] = '\0';
726     }
727
728     char ia64Ref[ABI_NAME_MAX_LENGTH];
729     if (x8664LibValid) {
730         snprintf(ia64Ref, ABI_NAME_MAX_LENGTH, "%s", X8664ABI);
731     } else {
732         ia64Ref[0] = '\0';
733     }
734
735     char* retAbiName = sysPreferAbiName;
736     do {
737         // # The basic rule is:
738         // - on 32 bit system, compare ia32Ref native libraries with
739         // arm32Ref native libraries. If pass, return ia32Ref .
740         // If fail, return arm32Ref.
741         // - on 64 bit system, IA has two chances. if ia64Ref native
742         // libraries can't pass the comparation with arm64Ref, we should
743         // run the comparation again with ia32Ref
744         if (is64BitPrefer) {
745             if (!compare(arm64Ref, ia64Ref, sysPreferAbiName, &retAbiName)) {
746                 char rawRes[ABI_NAME_MAX_LENGTH];
747                 snprintf(rawRes, ABI_NAME_MAX_LENGTH, "%s", retAbiName);
748                 compare(arm32Ref, ia32Ref, rawRes, &retAbiName);
749             }
750         } else {
751             compare(arm32Ref, ia32Ref, sysPreferAbiName, &retAbiName);
752         }
753     } while (0);
754     int ret = getAbiIndex(retAbiName);
755     ALOGI("selected abi %s(%d) for %s", retAbiName, ret, mpkgName);
756     return ret;
757 }
758
759 }  // namespace android