OSDN Git Service

Reduce the overhead of the PRC compatibility package feature during system bootup
authorxiajiang <xia1.jiang@intel.com>
Mon, 21 Mar 2016 16:26:06 +0000 (12:26 -0400)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Tue, 29 May 2018 10:07:25 +0000 (18:07 +0800)
The PRC compatibility package introduced too heavy overhead
in system bootup. This commit aims to reduce the overhead
in system bootup and improve the performance of PRC
compatibility package.

NOTE: The format of ThirdPartySO has been changed to improve
the performance. From now on, the lib name should be trimmed
as below if want to add into the list. For "libabc_v1_2_3.so",
add "abc_v" into the list, that is, the version information
at the tail of lib name should be removed.

Change-Id: Ic374e363d3d31f9bd69be839b33b1bd65950ef61
Tracked-On:https://jira01.devtools.intel.com/browse/OAM-25819
Signed-off-by: xiajiang <xia1.jiang@intel.com>
Reviewed-on: https://android.intel.com:443/484542

core/java/com/android/internal/content/NativeLibraryHelper.java
core/jni/abipicker/ABIPicker.cpp
core/jni/abipicker/ABIPicker.h
core/jni/com_android_internal_content_NativeLibraryHelper.cpp

index bcea437..8fd0279 100644 (file)
@@ -78,6 +78,7 @@ public class NativeLibraryHelper {
         final boolean extractNativeLibs;
         final boolean debuggable;
         final String pkgName;
+        final String apkDir;
 
         public static Handle create(File packageFile) throws IOException {
             try {
@@ -89,19 +90,34 @@ public class NativeLibraryHelper {
         }
 
         public static Handle create(Package pkg) throws IOException {
+            String apkdir;
+            if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                apkdir = null;
+            } else {
+                apkdir = pkg.codePath;
+            }
             return create(pkg.getAllCodePaths(),
                     (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0,
                     (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0,
-                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, pkg.packageName);
+                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, pkg.packageName, apkdir);
         }
 
         public static Handle create(PackageLite lite) throws IOException {
+            String apkdir;
+            if (lite.codePath == null ||
+                lite.codePath.startsWith("/system/") ||
+                lite.codePath.startsWith("/vendor/") ||
+                lite.codePath.startsWith("/oem/")) {
+                apkdir = null;
+            } else {
+                apkdir = lite.codePath;
+            }
             return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs,
-                    lite.debuggable, lite.packageName);
+                    lite.debuggable, lite.packageName, apkdir);
         }
 
         private static Handle create(List<String> codePaths, boolean multiArch,
-                boolean extractNativeLibs, boolean debuggable, String pkgName) throws IOException {
+                boolean extractNativeLibs, boolean debuggable, String pkgName, String apkdir) throws IOException {
             final int size = codePaths.size();
             final long[] apkHandles = new long[size];
             for (int i = 0; i < size; i++) {
@@ -116,16 +132,17 @@ public class NativeLibraryHelper {
                 }
             }
 
-            return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable, pkgName);
+            return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable, pkgName, apkdir);
         }
 
         Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs,
-                boolean debuggable, String pkgName) {
+                boolean debuggable, String pkgName, String apkdir) {
             this.apkHandles = apkHandles;
             this.multiArch = multiArch;
             this.extractNativeLibs = extractNativeLibs;
             this.debuggable = debuggable;
             this.pkgName = pkgName;
+            this.apkDir = apkdir;
             mGuard.open("close");
         }
 
@@ -200,12 +217,8 @@ public class NativeLibraryHelper {
     public static int findSupportedAbi(Handle handle, String[] supportedAbis) {
         int finalRes = NO_NATIVE_LIBRARIES;
         for (long apkHandle : handle.apkHandles) {
-            int res;
-            if (true) {
-                res = nativeFindSupportedAbiReplace(apkHandle, supportedAbis, handle.debuggable, handle.pkgName);
-            } else {
-                res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable);
-            }
+            final int res = nativeFindSupportedAbiReplace(apkHandle, supportedAbis,
+                    handle.debuggable, handle.pkgName, handle.apkDir);
 
             if (res == NO_NATIVE_LIBRARIES) {
                 // No native code, keep looking through all APKs.
@@ -228,11 +241,8 @@ public class NativeLibraryHelper {
         return finalRes;
     }
 
-    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis,
-            boolean debuggable);
-
     private native static int nativeFindSupportedAbiReplace(long handle, String[] supportedAbis,
-            boolean debuggable, String pkgName);
+            boolean debuggable, String pkgName, String apkdir);
 
     // Convenience method to call removeNativeBinariesFromDirLI(File)
     public static void removeNativeBinariesLI(String nativeLibraryPath) {
index 187ac56..fcfb371 100644 (file)
@@ -40,11 +40,12 @@ static bool thirdload = false;
 static bool whiteload = false;
 static bool blackload = false;
 
-static const char* iaRelated[] = {"intel", "atom", "x86", "x64"};
+static const char* iaRelated[] = {"intel", "intl", "atom", "x86", "x64"};
 
 //////////////////////////////////////////////////////////////////////
 void getConfig(const char* cfgFile , Vector<char*>& cfgVec) {
     FILE* fp = fopen(cfgFile, "r");
+    assert(fp != NULL);
     int read = -1;
     char *line = NULL;
     size_t len = 0;
@@ -132,8 +133,14 @@ bool isReliableLib(Vector<char*>& libList) {
     int len = ARR_SIZE(iaRelated);
     for (unsigned i = 0; i < sz; i++) {
         for (int j=0; j < len; j++) {
-            if (NULL != strstr(libList[i], iaRelated[j])) {
-                return true;
+            char* p = NULL;
+            if (NULL != (p = strcasestr(libList[i], iaRelated[j]))) {
+                int lenIA = strlen(iaRelated[j]);
+                if (!isalpha(*(p+lenIA))) {
+                    if (!isalpha(*(p-1)) || (p == (libList[i] + 3))) {
+                        return true;
+                    }
+                }
             }
         }
     }
@@ -168,21 +175,47 @@ static bool isMixedLib(char* libCur, char* buffer) {
     return mixed;
 }
 
+// compare the given string with the length, igonre upper and lower
+// len must be less than the length of two string
+static bool ignoreCmp(const char* str1, const char* str2, int len){
+    assert (str1 != NULL && str2 != NULL);
+    assert ((len <= strlen(str1)) && (len <= strlen(str2)));
+    for (int i = 0 ; i < len; i++) {
+        if (str1[i] != str2[i]) {
+            if(isalpha(str1[i]) && isalpha(str2[i])
+                    && (abs((str1[i]-str2[i])) == 32)) {
+                continue;
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
 static bool isInThirdPartySOList(char* libName) {
-    if (!libName) return false;
+    assert (libName != NULL);
     size_t libLen = strlen(libName);
-    bool ret = false;
     size_t sz = thirdPartySO.size();
     for (size_t i = 0; i < sz; i++) {
+        // thirdPartySO[i] won't be NULL
         size_t n = strlen(thirdPartySO[i]);
-        // three for prefix "lib", and 3 for suffix ".so"
-        if ((libLen == (n+6))&&(0 == strncmp(libName + 3, thirdPartySO[i], n))) {
-            ret = true;
-            break;
+        // three char for ".so"
+        int j = libLen - 4;
+        // now only '-' '-' and '.'found
+        while((j >= 0) && (isdigit(libName[j]) || (libName[j] == '-')
+              || (libName[j] == '_') || (libName[j] == '.'))) {
+            j--;
         }
+        // three char for "lib" and include the name with no letters
+        if ((j == 2) || ((size_t)j == (n+2))) {
+            if (ignoreCmp(libName+3, thirdPartySO[i], n)) {
+                P_LOG("ABIpicker libName %s,In Third", libName);
+                return true;
+            }
+        }
+
     }
-    P_LOG("ABIpicker libName %s,In Third %d", libName, ret);
-    return ret;
+    return false;
 }
 
 static void insertionSort(Vector<char*>& list) {
@@ -205,9 +238,9 @@ static void insertionSort(Vector<char*>& list) {
 
 //////////////////////////////////////////////////////////////////////
 // Use armRef as a reference, compare all libraries of iaRef with all
-// libraries of armRef. If both are match, iaRef will be returned with
-// *result and true is return value. Or else, *result is rawResult and
-// false is return value
+// libraries of armRef.If the two are match or iaRef is more, iaRef
+// will be returned with *result and true is return value. Or else,
+// *result is rawResult and false is return value
 bool ABIPicker::compare(char* armRef, char* iaRef,
                         char* rawResult, char** result) {
     bool ret = true;
@@ -231,6 +264,8 @@ bool ABIPicker::compare(char* armRef, char* iaRef,
         Vector<char*>* armRefList = getLibList(armRef);
 
         // if contains the key words in iaRelated, just return true
+        assert(iaRefList != NULL);
+        assert(armRefList != NULL);
         if (isReliableLib(*iaRefList)) {
             *result = iaRef;
             break;
@@ -257,7 +292,7 @@ bool ABIPicker::compare(char* armRef, char* iaRef,
 
         *result = armRef;
         ret = false;
-    } while (false);
+    } while (0);
 
     ALOGV("%s Vs. %s, return %s\n",
             iaRef ? iaRef : "NULL",
@@ -267,28 +302,48 @@ bool ABIPicker::compare(char* armRef, char* iaRef,
 
 bool ABIPicker::compareLibList(Vector<char*>& iaRefList,
         Vector<char*>& armRefList) {
-    if (iaRefList.size() != armRefList.size()) {
+
+    unsigned iaSize = iaRefList.size();
+    unsigned armSize = armRefList.size();
+    if (iaSize < armSize) {
         return false;
+    } else if (iaSize == 0 && armSize == 0) {
+        return true;
     }
 
+    int iaNum = 0;
+    int armNum = 0;
     Vector<char*>::iterator itIa = iaRefList.begin();
     Vector<char*>::iterator itArm = armRefList.begin();
+    bool isEqual = false;
     while (itIa != iaRefList.end() && itArm != armRefList.end()) {
-        char* iaLibName = *itIa;
-        char* armLibName = *itArm;
-
-        // NOTE:
-        // WIN treats file names in-case-sensitive,
-        // but LINUX  treats them case-sensitive.
-        if (0 != strcmp(iaLibName, armLibName)) {
+        if ((iaSize-iaNum) < (armSize-armNum)) {
             return false;
         }
-
-        itIa++;
+        isEqual = false ;
+        char* armLibName = *itArm;
+        int armLen = strlen (armLibName);
+        armNum++;
+
+        while (itIa != iaRefList.end() && !isEqual) {
+            char* iaLibName = *itIa;
+            iaNum++;
+            int iaLen = strlen (iaLibName);
+            if (iaLen == armLen) {
+                if (ignoreCmp(iaLibName, armLibName, iaLen)) {
+                    isEqual = true;
+                }
+            }
+            itIa++;
+        }
         itArm++;
     }
-
-    return true;
+    // till the end, and the last result is equal
+    if (itArm == armRefList.end() && isEqual){
+        return true;
+    } else {
+        return false;
+    }
 }
 
 bool ABIPicker::compare3rdPartyLibList(
@@ -296,6 +351,8 @@ bool ABIPicker::compare3rdPartyLibList(
                 size_t* iaIsvLibCount, size_t* armIsvLibCount) {
     Vector<char*>* iaRefList = getLibList(iaRef);
     Vector<char*>* armRefList = getLibList(armRef);
+    assert(iaRefList != NULL);
+    assert(armRefList != NULL);
 
     Vector<char*>* armRef3rdPartyLibList = new Vector<char*>();
     Vector<char*>::iterator itArm = armRefList->begin();
@@ -328,7 +385,12 @@ bool ABIPicker::compare3rdPartyLibList(
 
         itIa++;
     }
-    return compareLibList(*iaRef3rdPartyLibList, *armRef3rdPartyLibList);
+    bool result = compareLibList(*iaRef3rdPartyLibList, *armRef3rdPartyLibList);
+
+    //release the memory
+    free(armRef3rdPartyLibList);
+    free(iaRef3rdPartyLibList);
+    return result;
 }
 
 char* ABIPicker::getAbiName(int abi) {
@@ -414,7 +476,7 @@ ABIPicker::ABIPicker(const char* pkgName, Vector<ScopedUtfChars*> abiList) {
     if (!mpkgName) {
         P_LOG("ABIPicker Construct Allocated space fails");
     } else {
-        strcpy(mpkgName, pkgName);
+        snprintf(mpkgName, strlen(pkgName)+1, "%s", pkgName);
     }
     Vector<ScopedUtfChars*>::iterator it = abiList.begin();
     while (it != abiList.end()) {
@@ -453,6 +515,7 @@ ABIPicker::~ABIPicker(void) {
         it++;
     }
     mLibList->clear();
+    delete(mLibList);
 }
 
 bool ABIPicker::buildNativeLibList(void* apkHandle) {
@@ -510,7 +573,7 @@ bool ABIPicker::buildNativeLibList(void* apkHandle) {
             ret = false;
             break;
         }
-
+        memset(unCompBuff, 0, unCompLen);
         // THE MOST TIME COST OPERATION
         if (!zipFile->uncompressEntry(next, unCompBuff, unCompLen)) {
             ALOGE("%s: uncompress failed\n", fileName);
@@ -572,7 +635,7 @@ bool ABIPicker::buildNativeLibList(void* apkHandle) {
                     ret = false;
                     break;
                 }
-                strcpy(mixedLib, (char*)IMPOSSIBLE_LIB_NAME);
+                snprintf(mixedLib, (IMPOSSIBLE_LIB_LEN+1), "%s", IMPOSSIBLE_LIB_NAME);
                 mixedLib[IMPOSSIBLE_LIB_LEN] ='\0';
                 libListOfCurAbi->push_back(mixedLib);
                 continue;
@@ -588,7 +651,7 @@ bool ABIPicker::buildNativeLibList(void* apkHandle) {
             ret = false;
             break;
         }
-        strcpy(curLibName, lastSlash);
+        snprintf(curLibName,libNameSize+1, "%s", lastSlash);
         curLibName[libNameSize] = '\0';
 
         libListOfCurAbi->push_back(curLibName);
@@ -679,13 +742,13 @@ int ABIPicker::pickupRightABI(int sysPrefer) {
         if (is64BitPrefer) {
             if (!compare(arm64Ref, ia64Ref, sysPreferAbiName, &retAbiName)) {
                 char rawRes[ABI_NAME_MAX_LENGTH];
-                strcpy(rawRes, retAbiName);
+                snprintf(rawRes, ABI_NAME_MAX_LENGTH, "%s", retAbiName);
                 compare(arm32Ref, ia32Ref, rawRes, &retAbiName);
             }
         } else {
             compare(arm32Ref, ia32Ref, sysPreferAbiName, &retAbiName);
         }
-    } while (false);
+    } while (0);
     int ret = getAbiIndex(retAbiName);
     ALOGI("selected abi %s(%d) for %s", retAbiName, ret, mpkgName);
     return ret;
index 3645364..4f57de7 100644 (file)
@@ -7,7 +7,7 @@
 #include <sys/types.h>
 
 #include <ScopedUtfChars.h>
-#include <assert.h>
+
 namespace android {
 //  assumption: the length of name of any abi type in abi list,
 //  like armeabi-v7a, armeabi, x86, is not longer than 64
index 7d4c69d..e355679 100644 (file)
@@ -518,53 +518,82 @@ com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env,
 }
 
 static jint
-com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
-        jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable)
-{
-    return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
-}
-
-static jint
 com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace(
         JNIEnv *env,
         jclass clazz,
         jlong apkHandle,
         jobjectArray javaCpuAbisToSearch,
         jboolean debuggable,
-        jstring apkPkgName)
+        jstring apkPkgName,
+        jstring apkDir)
 {
 #ifdef _PRC_COMPATIBILITY_PACKAGE_
+
+    int abiType = findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
+    if (apkDir == NULL) {
+        return (jint)abiType;
+    }
+
+    char abiFlag[256] = {'\0'};
+    ScopedUtfChars apkdir(env, apkDir);
+    size_t apkdir_size = apkdir.size();
     const int numAbis = env->GetArrayLength(javaCpuAbisToSearch);
     Vector<ScopedUtfChars*> supportedAbis;
+
+    assert(apkdir_size < 256 - 15);
+    strcpy(abiFlag, apkdir.c_str());
+    abiFlag[apkdir_size] = '/';
+    abiFlag[apkdir_size + 1] = '.';
     for (int i = 0; i < numAbis; i++) {
         ScopedUtfChars* abiName = new ScopedUtfChars(env,
-                 (jstring)env->GetObjectArrayElement(
-                     javaCpuAbisToSearch, i));
+                 (jstring)env->GetObjectArrayElement(javaCpuAbisToSearch, i));
+        if (strlcpy(abiFlag + apkdir_size + 2, abiName->c_str(), 256 - apkdir_size - 2)
+                == abiName->size()) {
+            if (access(abiFlag, F_OK) == 0) {
+                abiType = i;
+                for (int j = 0; j < i; ++j) {
+                    delete supportedAbis[j];
+                }
+                delete abiName;
+                return (jint)abiType;
+            }
+        }
+
         supportedAbis.push_back(abiName);
     }
 
-    int abiType = findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
     do {
+        if (abiType < 0 || abiType >= numAbis ) {
+            break;
+        }
+
+        if (0 != strcmp(supportedAbis[abiType]->c_str(), X86ABI) &&
+                0 != strcmp(supportedAbis[abiType]->c_str(), X8664ABI)) {
+            break;
+        }
 
-        if (abiType < 0 || abiType >= numAbis ) break ;
-       // if one package's name is on OEM's specific white list, then the
-        // package should be installed as default
         ScopedUtfChars name(env, apkPkgName);
-         if (isInOEMWhiteList(name.c_str())) {
+        if (NULL == name.c_str()) {
             break;
         }
 
-        if (0 != strcmp(supportedAbis[abiType]->c_str(), X86ABI) &&
-            0 != strcmp(supportedAbis[abiType]->c_str(), X8664ABI)){
+        if (isInOEMWhiteList(name.c_str())) {
             break;
         }
+
         ABIPicker picker(name.c_str(),supportedAbis);
         if (!picker.buildNativeLibList((void*)apkHandle)) {
             break;
         }
 
         abiType = picker.pickupRightABI(abiType);
-    } while (false);
+        if (abiType >= 0 && abiType < numAbis &&
+                (strlcpy(abiFlag + apkdir_size + 2, supportedAbis[abiType]->c_str(),
+                         256 - apkdir_size - 2) == supportedAbis[abiType]->size())) {
+            creat(abiFlag, 0644);
+        }
+
+    } while(0);
 
     for (int i = 0; i < numAbis; ++i) {
         delete supportedAbis[i];
@@ -636,11 +665,8 @@ static const JNINativeMethod gMethods[] = {
     {"nativeSumNativeBinaries",
             "(JLjava/lang/String;Z)J",
             (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
-    {"nativeFindSupportedAbi",
-            "(J[Ljava/lang/String;Z)I",
-            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
     {"nativeFindSupportedAbiReplace",
-            "(J[Ljava/lang/String;ZLjava/lang/String;)I",
+            "(J[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)I",
             (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace},
     {"hasRenderscriptBitcode", "(J)I",
             (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},