Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9023861b authored by JW Wang's avatar JW Wang
Browse files

Sort libraries to improve search performance

Bug: 263680288
Test: atest StagedInstallTest
Test: atest PackageManagerServiceBootTest
Test: atest AndroidPackageTest
Change-Id: Ic3f15393b90e9113f3a00c57d11d24ba2fa21fd6
parent e9492d2d
Loading
Loading
Loading
Loading
+31 −15
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@@ -159,13 +159,21 @@ public class AppStateHelper {
        return false;
    }

    private static boolean containsAny(Collection<String> list, Collection<String> which) {
        if (list.isEmpty()) {
            return false;
        }
        for (var element : which) {
            if (list.contains(element)) {
    /**
     * True if {@code arr} contains any element in {@code which}.
     * Both {@code arr} and {@code which} must be sorted in advance.
     */
    private static boolean containsAny(String[] arr, List<String> which) {
        int s1 = arr.length;
        int s2 = which.size();
        for (int i = 0, j = 0; i < s1 && j < s2; ) {
            int val = arr[i].compareTo(which.get(j));
            if (val == 0) {
                return true;
            } else if (val < 0) {
                ++i;
            } else {
                ++j;
            }
        }
        return false;
@@ -174,9 +182,9 @@ public class AppStateHelper {
    private void addLibraryDependency(ArraySet<String> results, List<String> libPackageNames) {
        var pmInternal = LocalServices.getService(PackageManagerInternal.class);

        var libraryNames = new ArraySet<String>();
        var staticSharedLibraryNames = new ArraySet<String>();
        var sdkLibraryNames = new ArraySet<String>();
        var libraryNames = new ArrayList<String>();
        var staticSharedLibraryNames = new ArrayList<String>();
        var sdkLibraryNames = new ArrayList<String>();
        for (var packageName : libPackageNames) {
            var pkg = pmInternal.getAndroidPackage(packageName);
            if (pkg == null) {
@@ -199,11 +207,19 @@ public class AppStateHelper {
            return;
        }

        pmInternal.forEachPackage(pkg -> {
            if (containsAny(pkg.getUsesLibraries(), libraryNames)
                    || containsAny(pkg.getUsesOptionalLibraries(), libraryNames)
                    || containsAny(pkg.getUsesStaticLibraries(), staticSharedLibraryNames)
                    || containsAny(pkg.getUsesSdkLibraries(), sdkLibraryNames)) {
        Collections.sort(libraryNames);
        Collections.sort(sdkLibraryNames);
        Collections.sort(staticSharedLibraryNames);

        pmInternal.forEachPackageState(pkgState -> {
            var pkg = pkgState.getPkg();
            if (pkg == null) {
                return;
            }
            if (containsAny(pkg.getUsesLibrariesSorted(), libraryNames)
                    || containsAny(pkg.getUsesOptionalLibrariesSorted(), libraryNames)
                    || containsAny(pkg.getUsesStaticLibrariesSorted(), staticSharedLibraryNames)
                    || containsAny(pkg.getUsesSdkLibrariesSorted(), sdkLibraryNames)) {
                results.add(pkg.getPackageName());
            }
        });
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.pm.parsing.pkg;

import android.annotation.NonNull;

import com.android.internal.content.om.OverlayConfig;
import com.android.server.pm.pkg.AndroidPackage;

@@ -31,5 +33,15 @@ import com.android.server.pm.pkg.AndroidPackage;
 */
public interface AndroidPackageInternal extends AndroidPackage,
        OverlayConfig.PackageProvider.Package {
    @NonNull
    String[] getUsesLibrariesSorted();

    @NonNull
    String[] getUsesOptionalLibrariesSorted();

    @NonNull
    String[] getUsesSdkLibrariesSorted();

    @NonNull
    String[] getUsesStaticLibrariesSorted();
}
+60 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import libcore.util.EmptyArray;
import java.io.File;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -404,6 +405,15 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,

    private List<AndroidPackageSplit> mSplits;

    @NonNull
    private String[] mUsesLibrariesSorted;
    @NonNull
    private String[] mUsesOptionalLibrariesSorted;
    @NonNull
    private String[] mUsesSdkLibrariesSorted;
    @NonNull
    private String[] mUsesStaticLibrariesSorted;

    @NonNull
    public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
            @NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
@@ -1377,6 +1387,19 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
        return usesLibraries;
    }

    @NonNull
    @Override
    public String[] getUsesLibrariesSorted() {
        if (mUsesLibrariesSorted == null) {
            // Note lazy-sorting here doesn't break immutability because it always
            // return the same content. In the case of multi-threading, data race in accessing
            // mUsesLibrariesSorted might result in unnecessary creation of sorted copies
            // which is OK because the case is quite rare.
            mUsesLibrariesSorted = sortLibraries(usesLibraries);
        }
        return mUsesLibrariesSorted;
    }

    @NonNull
    @Override
    public List<String> getUsesNativeLibraries() {
@@ -1389,6 +1412,15 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
        return usesOptionalLibraries;
    }

    @NonNull
    @Override
    public String[] getUsesOptionalLibrariesSorted() {
        if (mUsesOptionalLibrariesSorted == null) {
            mUsesOptionalLibrariesSorted = sortLibraries(usesOptionalLibraries);
        }
        return mUsesOptionalLibrariesSorted;
    }

    @NonNull
    @Override
    public List<String> getUsesOptionalNativeLibraries() {
@@ -1405,6 +1437,15 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
    @Override
    public List<String> getUsesSdkLibraries() { return usesSdkLibraries; }

    @NonNull
    @Override
    public String[] getUsesSdkLibrariesSorted() {
        if (mUsesSdkLibrariesSorted == null) {
            mUsesSdkLibrariesSorted = sortLibraries(usesSdkLibraries);
        }
        return mUsesSdkLibrariesSorted;
    }

    @Nullable
    @Override
    public String[][] getUsesSdkLibrariesCertDigests() { return usesSdkLibrariesCertDigests; }
@@ -1419,6 +1460,15 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
        return usesStaticLibraries;
    }

    @NonNull
    @Override
    public String[] getUsesStaticLibrariesSorted() {
        if (mUsesStaticLibrariesSorted == null) {
            mUsesStaticLibrariesSorted = sortLibraries(usesStaticLibraries);
        }
        return mUsesStaticLibrariesSorted;
    }

    @Nullable
    @Override
    public String[][] getUsesStaticLibrariesCertDigests() {
@@ -2650,6 +2700,16 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
        return this;
    }

    private static String[] sortLibraries(List<String> libraryNames) {
        int size = libraryNames.size();
        if (size == 0) {
            return EmptyArray.STRING;
        }
        var arr = libraryNames.toArray(EmptyArray.STRING);
        Arrays.sort(arr);
        return arr;
    }

    private void assignDerivedFields2() {
        mBaseAppInfoFlags = PackageInfoUtils.appInfoFlags(this, null);
        mBaseAppInfoPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(this, null);
+4 −0
Original line number Diff line number Diff line
@@ -89,6 +89,10 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag
        "sortReceivers",
        "sortServices",
        "setAllComponentsDirectBootAware",
        "getUsesLibrariesSorted",
        "getUsesOptionalLibrariesSorted",
        "getUsesSdkLibrariesSorted",
        "getUsesStaticLibrariesSorted",
        // Tested through setting minor/major manually
        "setLongVersionCode",
        "getLongVersionCode",