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

Commit d2faad6f authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

Perf regression fix on low-level devices.

New memory profile: https://pprof.corp.google.com/?id=ff8c0e95176111ac48babe3144022845&tab=bottomup&focus=computePackageStateHash (194K vs 164K). Still ok compared to 7M.

Bug: 197658234
Fixes: 197658234
Test: reboot and look at the "ssm.onStartUser-0_com.android.role.RoleService" line in logcat
Change-Id: I89312af2d24647174aa5c532ce30032ee8d6ef69
parent 2967ca7d
Loading
Loading
Loading
Loading
+51 −58
Original line number Original line Diff line number Diff line
@@ -47,11 +47,13 @@ import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;


import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Collections;
@@ -302,49 +304,53 @@ public class RoleServicePlatformHelperImpl implements RoleServicePlatformHelper
    public String computePackageStateHash(@UserIdInt int userId) {
    public String computePackageStateHash(@UserIdInt int userId) {
        PackageManagerInternal packageManagerInternal = LocalServices.getService(
        PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
                PackageManagerInternal.class);
        final MessageDigestUtils md = new MessageDigestUtils();
        final MessageDigestOutputStream mdos = new MessageDigestOutputStream();


        DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(mdos));
        packageManagerInternal.forEachInstalledPackage(pkg -> {
        packageManagerInternal.forEachInstalledPackage(pkg -> {
            md.writeString(pkg.getPackageName());
            try {
            md.writeLong(pkg.getLongVersionCode());
                dataOutputStream.writeUTF(pkg.getPackageName());
            md.writeInt(packageManagerInternal.getApplicationEnabledState(pkg.getPackageName(),
                dataOutputStream.writeLong(pkg.getLongVersionCode());
                    userId));
                dataOutputStream.writeInt(packageManagerInternal.getApplicationEnabledState(
                        pkg.getPackageName(), userId));


                final List<String> requestedPermissions = pkg.getRequestedPermissions();
                final List<String> requestedPermissions = pkg.getRequestedPermissions();
                final int requestedPermissionsSize = requestedPermissions.size();
                final int requestedPermissionsSize = requestedPermissions.size();
            md.writeInt(requestedPermissionsSize);
                dataOutputStream.writeInt(requestedPermissionsSize);
                for (int i = 0; i < requestedPermissionsSize; i++) {
                for (int i = 0; i < requestedPermissionsSize; i++) {
                md.writeString(requestedPermissions.get(i));
                    dataOutputStream.writeUTF(requestedPermissions.get(i));
                }
                }


            final ArraySet<String> enabledComponents = packageManagerInternal.getEnabledComponents(
                final ArraySet<String> enabledComponents =
                    pkg.getPackageName(), userId);
                        packageManagerInternal.getEnabledComponents(pkg.getPackageName(), userId);
                final int enabledComponentsSize = CollectionUtils.size(enabledComponents);
                final int enabledComponentsSize = CollectionUtils.size(enabledComponents);
            md.writeInt(enabledComponentsSize);
                dataOutputStream.writeInt(enabledComponentsSize);
                for (int i = 0; i < enabledComponentsSize; i++) {
                for (int i = 0; i < enabledComponentsSize; i++) {
                md.writeString(enabledComponents.valueAt(i));
                    dataOutputStream.writeUTF(enabledComponents.valueAt(i));
                }
                }


                final ArraySet<String> disabledComponents =
                final ArraySet<String> disabledComponents =
                        packageManagerInternal.getDisabledComponents(pkg.getPackageName(), userId);
                        packageManagerInternal.getDisabledComponents(pkg.getPackageName(), userId);
                final int disabledComponentsSize = CollectionUtils.size(disabledComponents);
                final int disabledComponentsSize = CollectionUtils.size(disabledComponents);
                for (int i = 0; i < disabledComponentsSize; i++) {
                for (int i = 0; i < disabledComponentsSize; i++) {
                md.writeString(disabledComponents.valueAt(i));
                    dataOutputStream.writeUTF(disabledComponents.valueAt(i));
                }
                }


                for (final Signature signature : pkg.getSigningDetails().getSignatures()) {
                for (final Signature signature : pkg.getSigningDetails().getSignatures()) {
                md.writeBytes(signature.toByteArray());
                    dataOutputStream.write(signature.toByteArray());
                }
            } catch (IOException e) {
                // Never happens for MessageDigestOutputStream and DataOutputStream.
                throw new AssertionError(e);
            }
            }
        }, userId);
        }, userId);

        return mdos.getDigestAsString();
        return md.getDigestAsString();
    }
    }


    private static class MessageDigestUtils {
    private static class MessageDigestOutputStream extends OutputStream {
        private final byte[] mBuffer = new byte[8];
        private final MessageDigest mMessageDigest;
        private final MessageDigest mMessageDigest;


        MessageDigestUtils() {
        MessageDigestOutputStream() {
            try {
            try {
                mMessageDigest = MessageDigest.getInstance("SHA256");
                mMessageDigest = MessageDigest.getInstance("SHA256");
            } catch (NoSuchAlgorithmException e) {
            } catch (NoSuchAlgorithmException e) {
@@ -358,32 +364,19 @@ public class RoleServicePlatformHelperImpl implements RoleServicePlatformHelper
            return HexEncoding.encodeToString(mMessageDigest.digest(), true /* uppercase */);
            return HexEncoding.encodeToString(mMessageDigest.digest(), true /* uppercase */);
        }
        }


        void writeBytes(@NonNull byte[] bytes) {
        @Override
            mMessageDigest.update(bytes);
        public void write(int b) throws IOException {
        }
            mMessageDigest.update((byte) b);

        void writeString(@NonNull String s) {
            mMessageDigest.update(s.getBytes(StandardCharsets.UTF_8));
        }
        }


        void writeLong(long v) {
        @Override
            mBuffer[0] = (byte) (v >>> 56);
        public void write(byte[] b) throws IOException {
            mBuffer[1] = (byte) (v >>> 48);
            mMessageDigest.update(b);
            mBuffer[2] = (byte) (v >>> 40);
            mBuffer[3] = (byte) (v >>> 32);
            mBuffer[4] = (byte) (v >>> 24);
            mBuffer[5] = (byte) (v >>> 16);
            mBuffer[6] = (byte) (v >>>  8);
            mBuffer[7] = (byte) (v >>>  0);
            mMessageDigest.update(mBuffer, 0, 8);
        }
        }


        void writeInt(int v) {
        @Override
            mBuffer[0] = (byte) (v >>> 24);
        public void write(byte[] b, int off, int len) throws IOException {
            mBuffer[1] = (byte) (v >>> 16);
            mMessageDigest.update(b, off, len);
            mBuffer[2] = (byte) (v >>>  8);
            mBuffer[3] = (byte) (v >>>  0);
            mMessageDigest.update(mBuffer, 0, 4);
        }
        }
    }
    }
}
}