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

Commit d46ae2ca authored by Andreas Gampe's avatar Andreas Gampe Committed by Gerrit Code Review
Browse files

Merge "PreloadCheck: Add support for regex checking"

parents 2d5af940 bb621f2d
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.preload.check;

import dalvik.system.DexFile;

import java.util.Collection;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NotInitializedRegex {
    public static void main(String[] args) throws Exception {
        Matcher m = Pattern.compile(args[0]).matcher("");
        boolean requiresMatch = args.length > 1 ? Boolean.parseBoolean(args[1]) : false;

        Collection<DexFile> dexFiles = Util.getBootDexFiles();
        int matched = 0, notMatched = 0;
        for (DexFile dexFile : dexFiles) {
            Enumeration<String> entries = dexFile.entries();
            while (entries.hasMoreElements()) {
                String entry = entries.nextElement();
                m.reset(entry);
                if (m.matches()) {
                    System.out.println(entry + ": match");
                    matched++;
                    check(entry);
                } else {
                    System.out.println(entry + ": no match");
                    notMatched++;
                }
            }
        }
        System.out.println("Matched: " + matched + " Not-Matched: " + notMatched);
        if (requiresMatch && matched == 0) {
            throw new RuntimeException("Did not find match");
        }
        System.out.println("OK");
    }

    private static void check(String name) {
        Util.assertNotInitialized(name, null);
    }
}
+54 −0
Original line number Diff line number Diff line
@@ -16,7 +16,18 @@

package com.android.preload.check;

import dalvik.system.DexFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

public class Util {
    private static Field statusField;
@@ -31,6 +42,49 @@ public class Util {
        }
    }

    public static Collection<DexFile> getBootDexFiles() throws Exception {
        Class<?> vmClassLoaderClass = Class.forName("java.lang.VMClassLoader");
        Method getResources = vmClassLoaderClass.getDeclaredMethod("getResources", String.class);
        getResources.setAccessible(true);
        LinkedList<DexFile> res = new LinkedList<>();
        for (int i = 1;; i++) {
            try {
                String name = "classes" + (i > 1 ? String.valueOf(i) : "") + ".dex";
                @SuppressWarnings("unchecked")
                List<URL> urls = (List<URL>) getResources.invoke(null, name);
                if (urls.isEmpty()) {
                    break;
                }
                for (URL url : urls) {
                    // Make temp copy, so we can use public API. Would be nice to use in-memory, but
                    // those are unstable.
                    String tmp = "/data/local/tmp/tmp.dex";
                    try (BufferedInputStream in = new BufferedInputStream(url.openStream());
                            BufferedOutputStream out = new BufferedOutputStream(
                                    new FileOutputStream(tmp))) {
                        byte[] buf = new byte[4096];
                        for (;;) {
                            int r = in.read(buf);
                            if (r == -1) {
                                break;
                            }
                            out.write(buf, 0, r);
                        }
                    }
                    try {
                        res.add(new DexFile(tmp));
                    } catch (Exception dexError) {
                        dexError.printStackTrace(System.out);
                    }
                    new File(tmp).delete();
                }
            } catch (Exception ignored) {
                break;
            }
        }
        return res;
    }

    public static boolean isInitialized(Class<?> klass) throws Exception {
        Object val = statusField.get(klass);
        if (val == null || !(val instanceof Integer)) {
+10 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.preload.check;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -97,6 +97,14 @@ public class PreloadCheck implements IDeviceTest {
        }
    }

    /**
     * Test the classes ending in NoPreloadHolder are not initialized.
     */
    @Test
    public void testNoPreloadHolder() throws Exception {
        run("com.android.preload.check.NotInitializedRegex", ".*NoPreloadHolder$", "true");
    }

    private void run(String cmd, String... args) throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append("app_process ")
@@ -107,7 +115,7 @@ public class PreloadCheck implements IDeviceTest {
            sb.append(' ').append(escape(arg));
        }
        String res = mTestDevice.executeShellCommand(sb.toString());
        assertEquals(sb.toString(), "OK", res.trim());
        assertTrue(sb.toString() + "\n===\n" + res, res.trim().endsWith("OK"));
    }

    private static String escape(String input) {