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

Commit f30fff25 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

[res] Optimize idmap data initialization in OMS

- Only load overlayable definitions for the needed apks
  intead of parsing their all resource tables

- Don't load any overlayable definitions for checking
  actor policies if no actor policies are defined for the
  device. Almost no one defines any

- Reduce the number of allocations for the most common
  operations in overlay settings

Bug: 282215580
Test: system boot + perf trace
Change-Id: I62d19761686d84b7dc643ef1f35588449a61cfbd
parent dda09bea
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -49,6 +49,13 @@ public class OverlayPaths {
    public static class Builder {
        final OverlayPaths mPaths = new OverlayPaths();

        public Builder() {}

        public Builder(@NonNull OverlayPaths base) {
            mPaths.mResourceDirs.addAll(base.getResourceDirs());
            mPaths.mOverlayPaths.addAll(base.getOverlayPaths());
        }

        /**
         * Adds a non-APK path to the contents of {@link OverlayPaths#getOverlayPaths()}.
         */
+1 −1
Original line number Diff line number Diff line
@@ -257,7 +257,7 @@ final class IdmapManager {
    private boolean matchesActorSignature(@NonNull AndroidPackage targetPackage,
            @NonNull AndroidPackage overlayPackage, int userId) {
        String targetOverlayableName = overlayPackage.getOverlayTargetOverlayableName();
        if (targetOverlayableName != null) {
        if (targetOverlayableName != null && !mPackageManager.getNamedActors().isEmpty()) {
            try {
                OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget(
                        targetPackage.getPackageName(), targetOverlayableName, userId);
+68 −47
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static android.os.Process.INVALID_UID;
import static android.os.Trace.TRACE_TAG_RRO;
import static android.os.Trace.traceBegin;
import static android.os.Trace.traceEnd;

import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;

import android.annotation.NonNull;
@@ -362,7 +363,7 @@ public final class OverlayManagerService extends SystemService {
                defaultPackages.add(packageName);
            }
        }
        return defaultPackages.toArray(new String[defaultPackages.size()]);
        return defaultPackages.toArray(new String[0]);
    }

    private final class OverlayManagerPackageMonitor extends PackageMonitor {
@@ -1143,9 +1144,10 @@ public final class OverlayManagerService extends SystemService {
    };

    private static final class PackageManagerHelperImpl implements PackageManagerHelper {
        private static class PackageStateUsers {
        private static final class PackageStateUsers {
            private PackageState mPackageState;
            private final Set<Integer> mInstalledUsers = new ArraySet<>();
            private Boolean mDefinesOverlayable = null;
            private final ArraySet<Integer> mInstalledUsers = new ArraySet<>();
            private PackageStateUsers(@NonNull PackageState packageState) {
                this.mPackageState = packageState;
            }
@@ -1160,7 +1162,7 @@ public final class OverlayManagerService extends SystemService {
        // state may lead to contradictions within OMS. Better then to lag
        // behind until all pending intents have been processed.
        private final ArrayMap<String, PackageStateUsers> mCache = new ArrayMap<>();
        private final Set<Integer> mInitializedUsers = new ArraySet<>();
        private final ArraySet<Integer> mInitializedUsers = new ArraySet<>();

        PackageManagerHelperImpl(Context context) {
            mContext = context;
@@ -1176,8 +1178,7 @@ public final class OverlayManagerService extends SystemService {
         */
        @NonNull
        public ArrayMap<String, PackageState> initializeForUser(final int userId) {
            if (!mInitializedUsers.contains(userId)) {
                mInitializedUsers.add(userId);
            if (mInitializedUsers.add(userId)) {
                mPackageManagerInternal.forEachPackageState((packageState -> {
                    if (packageState.getPkg() != null
                            && packageState.getUserStateOrDefault(userId).isInstalled()) {
@@ -1196,13 +1197,11 @@ public final class OverlayManagerService extends SystemService {
            return userPackages;
        }

        @Override
        @Nullable
        public PackageState getPackageStateForUser(@NonNull final String packageName,
        private PackageStateUsers getRawPackageStateForUser(@NonNull final String packageName,
                final int userId) {
            final PackageStateUsers pkg = mCache.get(packageName);
            if (pkg != null && pkg.mInstalledUsers.contains(userId)) {
                return pkg.mPackageState;
                return pkg;
            }
            try {
                if (!mPackageManager.isPackageAvailable(packageName, userId)) {
@@ -1216,8 +1215,14 @@ public final class OverlayManagerService extends SystemService {
            return addPackageUser(packageName, userId);
        }

        @NonNull
        private PackageState addPackageUser(@NonNull final String packageName,
        @Override
        public PackageState getPackageStateForUser(@NonNull final String packageName,
                final int userId) {
            final PackageStateUsers pkg = getRawPackageStateForUser(packageName, userId);
            return pkg != null ? pkg.mPackageState : null;
        }

        private PackageStateUsers addPackageUser(@NonNull final String packageName,
                final int user) {
            final PackageState pkg = mPackageManagerInternal.getPackageStateInternal(packageName);
            if (pkg == null) {
@@ -1229,20 +1234,20 @@ public final class OverlayManagerService extends SystemService {
        }

        @NonNull
        private PackageState addPackageUser(@NonNull final PackageState pkg,
        private PackageStateUsers addPackageUser(@NonNull final PackageState pkg,
                final int user) {
            PackageStateUsers pkgUsers = mCache.get(pkg.getPackageName());
            if (pkgUsers == null) {
                pkgUsers = new PackageStateUsers(pkg);
                mCache.put(pkg.getPackageName(), pkgUsers);
            } else {
            } else if (pkgUsers.mPackageState != pkg) {
                pkgUsers.mPackageState = pkg;
                pkgUsers.mDefinesOverlayable = null;
            }
            pkgUsers.mInstalledUsers.add(user);
            return pkgUsers.mPackageState;
            return pkgUsers;
        }


        @NonNull
        private void removePackageUser(@NonNull final String packageName, final int user) {
            final PackageStateUsers pkgUsers = mCache.get(packageName);
@@ -1260,15 +1265,15 @@ public final class OverlayManagerService extends SystemService {
            }
        }

        @Nullable
        public PackageState onPackageAdded(@NonNull final String packageName, final int userId) {
            return addPackageUser(packageName, userId);
            final var pu = addPackageUser(packageName, userId);
            return pu != null ? pu.mPackageState : null;
        }

        @Nullable
        public PackageState onPackageUpdated(@NonNull final String packageName,
                final int userId) {
            return addPackageUser(packageName, userId);
            final var pu = addPackageUser(packageName, userId);
            return pu != null ? pu.mPackageState : null;
        }

        public void onPackageRemoved(@NonNull final String packageName, final int userId) {
@@ -1308,22 +1313,30 @@ public final class OverlayManagerService extends SystemService {
            return (pkgs.length == 0) ? null : pkgs[0];
        }

        @Nullable
        @Override
        public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
                @NonNull String targetOverlayableName, int userId)
                throws IOException {
            var packageState = getPackageStateForUser(packageName, userId);
            var pkg = packageState == null ? null : packageState.getAndroidPackage();
            final var psu = getRawPackageStateForUser(packageName, userId);
            final var pkg = (psu == null || psu.mPackageState == null)
                    ? null : psu.mPackageState.getAndroidPackage();
            if (pkg == null) {
                throw new IOException("Unable to get target package");
            }

            if (Boolean.FALSE.equals(psu.mDefinesOverlayable)) {
                return null;
            }

            ApkAssets apkAssets = null;
            try {
                apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(),
                        ApkAssets.PROPERTY_ONLY_OVERLAYABLES);
                return apkAssets.getOverlayableInfo(targetOverlayableName);
                if (psu.mDefinesOverlayable == null) {
                    psu.mDefinesOverlayable = apkAssets.definesOverlayable();
                }
                return Boolean.FALSE.equals(psu.mDefinesOverlayable)
                        ? null : apkAssets.getOverlayableInfo(targetOverlayableName);
            } finally {
                if (apkAssets != null) {
                    try {
@@ -1337,16 +1350,19 @@ public final class OverlayManagerService extends SystemService {
        @Override
        public boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
                throws IOException {
            var packageState = getPackageStateForUser(targetPackageName, userId);
            var pkg = packageState == null ? null : packageState.getAndroidPackage();
            final var psu = getRawPackageStateForUser(targetPackageName, userId);
            var pkg = (psu == null || psu.mPackageState == null)
                    ? null : psu.mPackageState.getAndroidPackage();
            if (pkg == null) {
                throw new IOException("Unable to get target package");
            }

            if (psu.mDefinesOverlayable == null) {
                ApkAssets apkAssets = null;
                try {
                apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath());
                return apkAssets.definesOverlayable();
                    apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(),
                            ApkAssets.PROPERTY_ONLY_OVERLAYABLES);
                    psu.mDefinesOverlayable = apkAssets.definesOverlayable();
                } finally {
                    if (apkAssets != null) {
                        try {
@@ -1356,6 +1372,8 @@ public final class OverlayManagerService extends SystemService {
                    }
                }
            }
            return psu.mDefinesOverlayable;
        }

        @Override
        public void enforcePermission(String permission, String message) throws SecurityException {
@@ -1545,8 +1563,7 @@ public final class OverlayManagerService extends SystemService {
                final OverlayPaths frameworkOverlays =
                        mImpl.getEnabledOverlayPaths("android", userId, false);
                for (final String targetPackageName : targetPackageNames) {
                    final OverlayPaths.Builder list = new OverlayPaths.Builder();
                    list.addAll(frameworkOverlays);
                    final var list = new OverlayPaths.Builder(frameworkOverlays);
                    if (!"android".equals(targetPackageName)) {
                        list.addAll(mImpl.getEnabledOverlayPaths(targetPackageName, userId, true));
                    }
@@ -1558,19 +1575,23 @@ public final class OverlayManagerService extends SystemService {
            final HashSet<String> invalidPackages = new HashSet<>();
            pm.setEnabledOverlayPackages(userId, pendingChanges, updatedPackages, invalidPackages);

            if (DEBUG || !invalidPackages.isEmpty()) {
                for (final String targetPackageName : targetPackageNames) {
                    if (DEBUG) {
                    Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
                        Slog.d(TAG,
                                "-> Updating overlay: target=" + targetPackageName + " overlays=["
                                        + pendingChanges.get(targetPackageName)
                                        + "] userId=" + userId);
                    }

                    if (invalidPackages.contains(targetPackageName)) {
                        Slog.e(TAG, TextUtils.formatSimple(
                            "Failed to change enabled overlays for %s user %d", targetPackageName,
                                "Failed to change enabled overlays for %s user %d",
                                targetPackageName,
                                userId));
                    }
                }
            }
            return new ArrayList<>(updatedPackages);
        } finally {
            traceEnd(TRACE_TAG_RRO);
+5 −9
Original line number Diff line number Diff line
@@ -772,24 +772,20 @@ final class OverlayManagerServiceImpl {

    OverlayPaths getEnabledOverlayPaths(@NonNull final String targetPackageName,
            final int userId, boolean includeImmutableOverlays) {
        final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName,
                userId);
        final OverlayPaths.Builder paths = new OverlayPaths.Builder();
        final int n = overlays.size();
        for (int i = 0; i < n; i++) {
            final OverlayInfo oi = overlays.get(i);
        final var paths = new OverlayPaths.Builder();
        mSettings.forEachMatching(userId, null, targetPackageName, oi -> {
            if (!oi.isEnabled()) {
                continue;
                return;
            }
            if (!includeImmutableOverlays && !oi.isMutable) {
                continue;
                return;
            }
            if (oi.isFabricated()) {
                paths.addNonApkPath(oi.baseCodePath);
            } else {
                paths.addApkPath(oi.baseCodePath);
            }
        }
        });
        return paths.build();
    }

+18 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

@@ -182,6 +183,23 @@ final class OverlayManagerSettings {
        return CollectionUtils.map(items, SettingsItem::getOverlayInfo);
    }

    void forEachMatching(int userId, String overlayName, String targetPackageName,
            @NonNull Consumer<OverlayInfo> consumer) {
        for (int i = 0, n = mItems.size(); i < n; i++) {
            final SettingsItem item = mItems.get(i);
            if (item.getUserId() != userId) {
                continue;
            }
            if (overlayName != null && !item.mOverlay.getPackageName().equals(overlayName)) {
                continue;
            }
            if (targetPackageName != null && !item.mTargetPackageName.equals(targetPackageName)) {
                continue;
            }
            consumer.accept(item.getOverlayInfo());
        }
    }

    ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
        final List<SettingsItem> items = selectWhereUser(userId);