/*
 * Copyright (C) 2017 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.
 */

import java.lang.reflect.Method;
import java.util.Enumeration;

import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * DexFile tests (Dalvik-specific).
 */
public class Main {
    private static final String CLASS_PATH =
        System.getenv("DEX_LOCATION") + "/071-dexfile-map-clean-ex.jar";

    /**
     * Prep the environment then run the test.
     */
    public static void main(String[] args) throws Exception {
        // Load the dex file, this is a pre-requisite to mmap-ing it in.
        Class<?> AnotherClass = testDexFile();
        // Check that the memory maps are clean.
        testDexMemoryMaps();

        // Prevent garbage collector from collecting our DexFile
        // (and unmapping too early) by using it after we finish
        // our verification.
        AnotherClass.newInstance();
    }

    private static boolean checkSmapsEntry(String[] smapsLines, int offset) {
      String nameDescription = smapsLines[offset];
      String[] split = nameDescription.split(" ");

      String permissions = split[1];
      // Mapped as read-only + anonymous.
      if (!permissions.startsWith("r--p")) {
        return false;
      }

      boolean validated = false;

      // We have the right entry, now make sure it's valid.
      for (int i = offset; i < smapsLines.length; ++i) {
        String line = smapsLines[i];

        if (line.startsWith("Shared_Dirty") || line.startsWith("Private_Dirty")) {
          String lineTrimmed = line.trim();
          String[] lineSplit = lineTrimmed.split(" +");

          String sizeUsuallyInKb = lineSplit[lineSplit.length - 2];

          sizeUsuallyInKb = sizeUsuallyInKb.trim();

          if (!sizeUsuallyInKb.equals("0")) {
            System.out.println(
                "ERROR: Memory mapping for " + CLASS_PATH + " is unexpectedly dirty");
            System.out.println(line);
          } else {
            validated = true;
          }
        }

        // VmFlags marks the "end" of an smaps entry.
        if (line.startsWith("VmFlags")) {
          break;
        }
      }

      if (validated) {
        System.out.println("Secondary dexfile mmap is clean");
      } else {
        System.out.println("ERROR: Memory mapping is missing Shared_Dirty/Private_Dirty entries");
      }

      return true;
    }

    private static void testDexMemoryMaps() throws Exception {
        // Ensure that the secondary dex file is mapped clean (directly from JAR file).
        String smaps = new String(Files.readAllBytes(Paths.get("/proc/self/smaps")));

        String[] smapsLines = smaps.split("\n");
        boolean found = true;
        for (int i = 0; i < smapsLines.length; ++i) {
          if (smapsLines[i].contains(CLASS_PATH)) {
            if (checkSmapsEntry(smapsLines, i)) {
              return;
            } // else we found the wrong one, keep going.
          }
        }

        // Error case:
        System.out.println("Could not find " + CLASS_PATH + " RO-anonymous smaps entry");
        System.out.println(smaps);
    }

    private static Class<?> testDexFile() throws Exception {
        ClassLoader classLoader = Main.class.getClassLoader();
        Class<?> DexFile = classLoader.loadClass("dalvik.system.DexFile");
        Method DexFile_loadDex = DexFile.getMethod("loadDex",
                                                   String.class,
                                                   String.class,
                                                   Integer.TYPE);
        Method DexFile_entries = DexFile.getMethod("entries");
        Object dexFile = DexFile_loadDex.invoke(null, CLASS_PATH, null, 0);
        Enumeration<String> e = (Enumeration<String>) DexFile_entries.invoke(dexFile);
        while (e.hasMoreElements()) {
            String className = e.nextElement();
            System.out.println(className);
        }

        Method DexFile_loadClass = DexFile.getMethod("loadClass",
                                                     String.class,
                                                     ClassLoader.class);
        Class<?> AnotherClass = (Class<?>)DexFile_loadClass.invoke(dexFile,
            "Another", Main.class.getClassLoader());
        return AnotherClass;
    }
}
