Merge "CTS for b/64536115" into oc-mr1-dev
am: 090296aa57

Change-Id: I6170eedc26178efd14112b53f28b1b3cf2befcb0
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index c867649..befa0f1 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -2740,6 +2740,17 @@
                 android:value="android.software.live_tv" />
         </activity>
 
+        <activity android:name=".tv.MicrophoneDeviceTestActivity"
+                  android:label="@string/tv_microphone_device_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_tv" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.software.leanback" />
+        </activity>
+
         <activity android:name=".screenpinning.ScreenPinningTestActivity"
             android:label="@string/screen_pinning_test">
             <intent-filter>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 62f747d..6982c5e 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3478,6 +3478,35 @@
     2) You should see the text \"Cts App-Link Text\".\n
     </string>
 
+    <string name="tv_microphone_device_test">Microphone device test</string>
+    <string name="tv_microphone_device_test_info">
+    This test checks if InputDevice.hasMicrophone of the Media API reports a
+    correct value on every input device (including remote controls).
+    </string>
+    <string name="tv_microphone_device_test_prep_question">
+    Before continuing, please make sure that you pair all primary input
+    devices intended to be used by the device, including bluetooth
+    remotes and companion remote-control apps such as the Android TV Remote Control.
+    Have you paired every primary input device with the device under test (DUT)?
+    </string>
+    <string name="tv_microphone_device_test_mic_question">
+    Does input device \"%1$s\" have a microphone?
+    </string>
+    <string name="tv_microphone_device_test_negative_mismatch">
+    InputDevice.hasMicrophone reports that this input device DOES have a
+    microphone whereas you selected that it does not.  Please correct it by
+    declaring \"audio.mic = 0\" in the device\'s input device configuration
+    (.idc) file.
+    </string>
+    <string name="tv_microphone_device_test_positive_mismatch">
+    InputDevice.hasMicrophone reports that this input device does NOT have a
+    microphone whereas you selected that it does.  Please correct it by
+    declaring \"audio.mic = 1\" in the device\'s input device configuration
+    (.idc) file and make sure that relevant files such as key layout (.kl)
+    and key character map (.kcm) files are found by the system accordingly.
+    </string>
+    <string name="tv_microphone_device_test_no_input_devices">No input devices found.</string>
+
     <string name="overlay_view_text">Overlay View Dummy Text</string>
     <string name="custom_rating">Example of input app specific custom rating.</string>
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java
new file mode 100644
index 0000000..eca02c1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MicrophoneDeviceTestActivity.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.tv;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.View;
+import android.widget.Toast;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Tests for verifying that all input devices report correct hasMicrophone() states.
+ */
+@SuppressLint("NewApi")
+public class MicrophoneDeviceTestActivity extends TvAppVerifierActivity
+        implements View.OnClickListener {
+    private static final String TAG = "MicrophoneDeviceTestActivity";
+    private static final boolean PASS = true;
+
+    private InputManager mInputManager;
+    private HashMap<View, List<Object>> mInputDeviceItems;
+    private View mPreparationYesItem;
+    private View mPreparationNoItem;
+
+    @Override
+    public void onClick(View v) {
+        final View postTarget = getPostTarget();
+
+        if (containsButton(mPreparationYesItem, v)) {
+            setPassState(mPreparationYesItem, true);
+            setButtonEnabled(mPreparationNoItem, false);
+            createInputDeviceItems();
+            return;
+        } else if (containsButton(mPreparationNoItem, v)) {
+            setPassState(mPreparationYesItem, false);
+            setButtonEnabled(mPreparationNoItem, false);
+            getPassButton().setEnabled(false);
+            return;
+        } else if (mInputDeviceItems == null) {
+            return;
+        }
+
+        for (View item : mInputDeviceItems.keySet()) {
+            if (containsButton(item, v)) {
+                final List<Object> triple = mInputDeviceItems.get(item);
+                final boolean userAnswer = (boolean) triple.get(0);
+                final boolean actualAnswer = (boolean) triple.get(1);
+                final View pairedItem = (View) triple.get(2);
+
+                if (userAnswer == actualAnswer) {
+                    setPassState(userAnswer ? item : pairedItem, true);
+                    setButtonEnabled(userAnswer ? pairedItem : item, false);
+                    item.setTag(PASS); pairedItem.setTag(PASS);
+                    if (checkAllPassed()) {
+                        getPassButton().setEnabled(true);
+                    }
+                    return;
+                }
+
+                final int messageId =
+                    actualAnswer ? R.string.tv_microphone_device_test_negative_mismatch :
+                    R.string.tv_microphone_device_test_positive_mismatch;
+                Toast.makeText(this, messageId, Toast.LENGTH_LONG).show();
+                setPassState(userAnswer ? item : pairedItem, false);
+                getPassButton().setEnabled(false);
+                return;
+            }
+        }
+    }
+
+    @Override
+    protected void createTestItems() {
+        mPreparationYesItem = createUserItem(
+                R.string.tv_microphone_device_test_prep_question,
+                R.string.tv_yes, this);
+        setButtonEnabled(mPreparationYesItem, true);
+        mPreparationNoItem = createButtonItem(R.string.tv_no, this);
+        setButtonEnabled(mPreparationNoItem, true);
+    }
+
+    private void createInputDeviceItems() {
+        final Context context = MicrophoneDeviceTestActivity.this;
+        mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+
+        final int[] inputDeviceIds = mInputManager.getInputDeviceIds();
+        mInputDeviceItems = new HashMap<View, List<Object>>();
+
+        for (int inputDeviceId : inputDeviceIds) {
+            final InputDevice inputDevice = mInputManager.getInputDevice(inputDeviceId);
+            final boolean hasMicrophone = inputDevice.hasMicrophone();
+            Log.w(TAG, "name: " + inputDevice.getName() + ", mic: " + hasMicrophone + ", virtual: "
+                  + inputDevice.isVirtual() + ", descriptor: " + inputDevice.getDescriptor());
+
+            // Skip virtual input devices such as virtual keyboards.  This does
+            // not, e.g., include com.google.android.tv.remote bluetooth connections.
+            if (inputDevice.isVirtual()) {
+                continue;
+            }
+
+            final CharSequence micQuestion =
+                getString(R.string.tv_microphone_device_test_mic_question, inputDevice.getName());
+
+            final View inputDeviceYesItem = createUserItem(micQuestion, R.string.tv_yes, this);
+            setButtonEnabled(inputDeviceYesItem, true);
+            final View inputDeviceNoItem = createButtonItem(R.string.tv_no, this);
+            setButtonEnabled(inputDeviceNoItem, true);
+            mInputDeviceItems.put(
+                inputDeviceYesItem, Arrays.asList(true, hasMicrophone, inputDeviceNoItem));
+            mInputDeviceItems.put(
+                inputDeviceNoItem, Arrays.asList(false, hasMicrophone, inputDeviceYesItem));
+        }
+
+        if (mInputDeviceItems.size() == 0) {
+            Toast.makeText(this, R.string.tv_microphone_device_test_no_input_devices,
+                           Toast.LENGTH_LONG).show();
+            getPassButton().setEnabled(true);
+        }
+    }
+
+    @Override
+    protected void setInfoResources() {
+        setInfoResources(R.string.tv_microphone_device_test,
+                R.string.tv_microphone_device_test_info, -1);
+    }
+
+    private boolean hasPassed(View item) {
+        return (item.getTag() != null) && ((Boolean) item.getTag()) == PASS;
+    }
+
+    private boolean checkAllPassed() {
+        if (mInputDeviceItems != null && mInputDeviceItems.size() > 0) {
+            for (View item : mInputDeviceItems.keySet()) {
+                if (!hasPassed(item)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
index d580ef8..41ab6f7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
@@ -91,6 +91,22 @@
     }
 
     /**
+     * Call this to create a test step where the user must perform some action.
+     */
+    protected View createUserItem(CharSequence instructionCharSequence,
+                                  int buttonTextId, View.OnClickListener l) {
+        View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
+        TextView instructions = (TextView) item.findViewById(R.id.instructions);
+        instructions.setText(instructionCharSequence);
+        Button button = (Button) item.findViewById(R.id.user_action_button);
+        button.setVisibility(View.VISIBLE);
+        button.setText(buttonTextId);
+        button.setOnClickListener(l);
+        mItemList.addView(item);
+        return item;
+    }
+
+    /**
      * Call this to create a test step where the test automatically evaluates whether
      * an expected condition is satisfied.
      */
diff --git a/hostsidetests/jvmti/base/jni/cts_agent.cpp b/hostsidetests/jvmti/base/jni/cts_agent.cpp
index bb1e620..665a47e 100644
--- a/hostsidetests/jvmti/base/jni/cts_agent.cpp
+++ b/hostsidetests/jvmti/base/jni/cts_agent.cpp
@@ -49,7 +49,7 @@
     LOG(FATAL) << "Could not get shared jvmtiEnv";
   }
 
-  SetAllCapabilities(jvmti_env);
+  SetStandardCapabilities(jvmti_env);
   return 0;
 }
 
@@ -64,7 +64,7 @@
     LOG(FATAL) << "Could not get shared jvmtiEnv";
   }
 
-  SetAllCapabilities(jvmti_env);
+  SetStandardCapabilities(jvmti_env);
   InformMainAttach(jvmti_env, env, kMainClass, kMainClassStartup);
   return 0;
 }
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/kernel-headers/linux/ion.h b/hostsidetests/security/securityPatch/CVE-2017-0564/kernel-headers/linux/ion.h
new file mode 100644
index 0000000..7b5b031
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/kernel-headers/linux/ion.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+typedef int ion_user_handle_t;
+enum ion_heap_type {
+  ION_HEAP_TYPE_SYSTEM,
+  ION_HEAP_TYPE_SYSTEM_CONTIG,
+  ION_HEAP_TYPE_CARVEOUT,
+  ION_HEAP_TYPE_CHUNK,
+  ION_HEAP_TYPE_DMA,
+  ION_HEAP_TYPE_CUSTOM,
+};
+#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
+#define ION_FLAG_CACHED 1
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
+struct ion_allocation_data {
+  size_t len;
+  size_t align;
+  unsigned int heap_id_mask;
+  unsigned int flags;
+  ion_user_handle_t handle;
+};
+struct ion_fd_data {
+  ion_user_handle_t handle;
+  int fd;
+};
+struct ion_handle_data {
+  ion_user_handle_t handle;
+};
+struct ion_custom_data {
+  unsigned int cmd;
+  unsigned long arg;
+};
+#define MAX_HEAP_NAME 32
+struct ion_heap_data {
+  char name[MAX_HEAP_NAME];
+  __u32 type;
+  __u32 heap_id;
+  __u32 reserved0;
+  __u32 reserved1;
+  __u32 reserved2;
+};
+struct ion_heap_query {
+  __u32 cnt;
+  __u32 reserved0;
+  __u64 heaps;
+  __u32 reserved1;
+  __u32 reserved2;
+};
+#define ION_IOC_MAGIC 'I'
+#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_allocation_data)
+#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
+#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
+#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
+#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, struct ion_heap_query)
+#endif
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/original-kernel-headers/linux/ion.h b/hostsidetests/security/securityPatch/CVE-2017-0564/original-kernel-headers/linux/ion.h
new file mode 100644
index 0000000..14cd873
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/original-kernel-headers/linux/ion.h
@@ -0,0 +1,236 @@
+/*
+ * drivers/staging/android/uapi/ion.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+typedef int ion_user_handle_t;
+
+/**
+ * enum ion_heap_types - list of all possible types of heaps
+ * @ION_HEAP_TYPE_SYSTEM:	 memory allocated via vmalloc
+ * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
+ * @ION_HEAP_TYPE_CARVEOUT:	 memory allocated from a prereserved
+ *				 carveout heap, allocations are physically
+ *				 contiguous
+ * @ION_HEAP_TYPE_DMA:		 memory allocated via DMA API
+ * @ION_NUM_HEAPS:		 helper for iterating over heaps, a bit mask
+ *				 is used to identify the heaps, so only 32
+ *				 total heap types are supported
+ */
+enum ion_heap_type {
+	ION_HEAP_TYPE_SYSTEM,
+	ION_HEAP_TYPE_SYSTEM_CONTIG,
+	ION_HEAP_TYPE_CARVEOUT,
+	ION_HEAP_TYPE_CHUNK,
+	ION_HEAP_TYPE_DMA,
+	ION_HEAP_TYPE_CUSTOM, /*
+			       * must be last so device specific heaps always
+			       * are at the end of this enum
+			       */
+};
+
+#define ION_NUM_HEAP_IDS		(sizeof(unsigned int) * 8)
+
+/**
+ * allocation flags - the lower 16 bits are used by core ion, the upper 16
+ * bits are reserved for use by the heaps themselves.
+ */
+
+/*
+ * mappings of this buffer should be cached, ion will do cache maintenance
+ * when the buffer is mapped for dma
+ */
+#define ION_FLAG_CACHED 1
+
+/*
+ * mappings of this buffer will created at mmap time, if this is set
+ * caches must be managed manually
+ */
+#define ION_FLAG_CACHED_NEEDS_SYNC 2
+
+/**
+ * DOC: Ion Userspace API
+ *
+ * create a client by opening /dev/ion
+ * most operations handled via following ioctls
+ *
+ */
+
+/**
+ * struct ion_allocation_data - metadata passed from userspace for allocations
+ * @len:		size of the allocation
+ * @align:		required alignment of the allocation
+ * @heap_id_mask:	mask of heap ids to allocate from
+ * @flags:		flags passed to heap
+ * @handle:		pointer that will be populated with a cookie to use to
+ *			refer to this allocation
+ *
+ * Provided by userspace as an argument to the ioctl
+ */
+struct ion_allocation_data {
+	size_t len;
+	size_t align;
+	unsigned int heap_id_mask;
+	unsigned int flags;
+	ion_user_handle_t handle;
+};
+
+/**
+ * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair
+ * @handle:	a handle
+ * @fd:		a file descriptor representing that handle
+ *
+ * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with
+ * the handle returned from ion alloc, and the kernel returns the file
+ * descriptor to share or map in the fd field.  For ION_IOC_IMPORT, userspace
+ * provides the file descriptor and the kernel returns the handle.
+ */
+struct ion_fd_data {
+	ion_user_handle_t handle;
+	int fd;
+};
+
+/**
+ * struct ion_handle_data - a handle passed to/from the kernel
+ * @handle:	a handle
+ */
+struct ion_handle_data {
+	ion_user_handle_t handle;
+};
+
+/**
+ * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl
+ * @cmd:	the custom ioctl function to call
+ * @arg:	additional data to pass to the custom ioctl, typically a user
+ *		pointer to a predefined structure
+ *
+ * This works just like the regular cmd and arg fields of an ioctl.
+ */
+struct ion_custom_data {
+	unsigned int cmd;
+	unsigned long arg;
+};
+
+#define MAX_HEAP_NAME			32
+
+/**
+ * struct ion_heap_data - data about a heap
+ * @name - first 32 characters of the heap name
+ * @type - heap type
+ * @heap_id - heap id for the heap
+ */
+struct ion_heap_data {
+	char name[MAX_HEAP_NAME];
+	__u32 type;
+	__u32 heap_id;
+	__u32 reserved0;
+	__u32 reserved1;
+	__u32 reserved2;
+};
+
+/**
+ * struct ion_heap_query - collection of data about all heaps
+ * @cnt - total number of heaps to be copied
+ * @heaps - buffer to copy heap data
+ */
+struct ion_heap_query {
+	__u32 cnt; /* Total number of heaps to be copied */
+	__u32 reserved0; /* align to 64bits */
+	__u64 heaps; /* buffer to be populated */
+	__u32 reserved1;
+	__u32 reserved2;
+};
+
+#define ION_IOC_MAGIC		'I'
+
+/**
+ * DOC: ION_IOC_ALLOC - allocate memory
+ *
+ * Takes an ion_allocation_data struct and returns it with the handle field
+ * populated with the opaque handle for the allocation.
+ */
+#define ION_IOC_ALLOC		_IOWR(ION_IOC_MAGIC, 0, \
+				      struct ion_allocation_data)
+
+/**
+ * DOC: ION_IOC_FREE - free memory
+ *
+ * Takes an ion_handle_data struct and frees the handle.
+ */
+#define ION_IOC_FREE		_IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+
+/**
+ * DOC: ION_IOC_MAP - get a file descriptor to mmap
+ *
+ * Takes an ion_fd_data struct with the handle field populated with a valid
+ * opaque handle.  Returns the struct with the fd field set to a file
+ * descriptor open in the current address space.  This file descriptor
+ * can then be used as an argument to mmap.
+ */
+#define ION_IOC_MAP		_IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
+
+/**
+ * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
+ *
+ * Takes an ion_fd_data struct with the handle field populated with a valid
+ * opaque handle.  Returns the struct with the fd field set to a file
+ * descriptor open in the current address space.  This file descriptor
+ * can then be passed to another process.  The corresponding opaque handle can
+ * be retrieved via ION_IOC_IMPORT.
+ */
+#define ION_IOC_SHARE		_IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
+
+/**
+ * DOC: ION_IOC_IMPORT - imports a shared file descriptor
+ *
+ * Takes an ion_fd_data struct with the fd field populated with a valid file
+ * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle
+ * filed set to the corresponding opaque handle.
+ */
+#define ION_IOC_IMPORT		_IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
+
+/**
+ * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory
+ *
+ * Deprecated in favor of using the dma_buf api's correctly (syncing
+ * will happen automatically when the buffer is mapped to a device).
+ * If necessary should be used after touching a cached buffer from the cpu,
+ * this will make the buffer in memory coherent.
+ */
+#define ION_IOC_SYNC		_IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+
+/**
+ * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
+ *
+ * Takes the argument of the architecture specific ioctl to call and
+ * passes appropriate userdata for that ioctl
+ */
+#define ION_IOC_CUSTOM		_IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
+
+/**
+ * DOC: ION_IOC_HEAP_QUERY - information about available heaps
+ *
+ * Takes an ion_heap_query structure and populates information about
+ * available Ion heaps.
+ */
+#define ION_IOC_HEAP_QUERY     _IOWR(ION_IOC_MAGIC, 8, \
+					struct ion_heap_query)
+
+#endif /* _UAPI_LINUX_ION_H */
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
index 7734d4c..ae5ad40 100644
--- a/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
@@ -29,7 +29,11 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <linux/ion.h>
+
+// Include a fixed version of the ion.h file because it changes per kernel.
+// This test is going to be extremely brittle due to it's dependency on
+// a structure that is going to change with different kernels.
+#include "kernel-headers/linux/ion.h"
 
 #define ION_HEAP(bit) (1 << (bit))
 
@@ -73,7 +77,7 @@
 #ifdef NEW_ION
         .heap_id_mask = ion_type,
         //.flags = ION_SECURE | ION_FORCE_CONTIGUOUS,
-        .flags = (1 << 0),
+        //.flags = (1 << 0),
         .flags = 0x0,
 #else
         .flags = ION_SECURE | ION_FORCE_CONTIGUOUS | ION_HEAP(ION_CP_MM_HEAP_ID),
@@ -165,7 +169,7 @@
 
 int main()
 {
-    int ret, i, count;
+    int ret, count;
     pthread_t tid_free[2];
 
     count = 0;
@@ -178,6 +182,7 @@
 	return -1;
     }
 
+    size_t i;
     for (i=0; i < sizeof(ion_type)/sizeof(ion_type[0]); i++) {
         ret = ion_alloc(ion_fd, 0x1000, &ion_handle, ion_type[i]);
         if (ret == 0) {
diff --git a/suite/audio_quality/lib/src/task/ModelBuilder.cpp b/suite/audio_quality/lib/src/task/ModelBuilder.cpp
index 78e5138..f1a506b 100644
--- a/suite/audio_quality/lib/src/task/ModelBuilder.cpp
+++ b/suite/audio_quality/lib/src/task/ModelBuilder.cpp
@@ -87,7 +87,7 @@
 {
     XMLDocument doc;
     int error = doc.LoadFile(xmlFileName.string());
-    if (error != XML_NO_ERROR) {
+    if (error != XML_SUCCESS) {
         LOGE("ModelBuilder::parseTestDescriptionXml cannot load file %s: %d", xmlFileName.string(), error);
         return NULL;
     }
diff --git a/tests/tests/jni/libjninamespacea1/namespacea1.cpp b/tests/tests/jni/libjninamespacea1/namespacea1.cpp
index decb4f1..8a79c3c 100644
--- a/tests/tests/jni/libjninamespacea1/namespacea1.cpp
+++ b/tests/tests/jni/libjninamespacea1/namespacea1.cpp
@@ -18,7 +18,7 @@
 
 #include <android/log.h>
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,"namespacea1",__VA_ARGS__)
 
diff --git a/tests/tests/jni/libjninamespacea2/namespacea2.cpp b/tests/tests/jni/libjninamespacea2/namespacea2.cpp
index 809266e..49f055e 100644
--- a/tests/tests/jni/libjninamespacea2/namespacea2.cpp
+++ b/tests/tests/jni/libjninamespacea2/namespacea2.cpp
@@ -18,7 +18,7 @@
 
 #include <android/log.h>
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,"namespacea2",__VA_ARGS__)
 
diff --git a/tests/tests/jni/libjninamespaceb/namespaceb.cpp b/tests/tests/jni/libjninamespaceb/namespaceb.cpp
index b3bedcb..4c48627 100644
--- a/tests/tests/jni/libjninamespaceb/namespaceb.cpp
+++ b/tests/tests/jni/libjninamespaceb/namespaceb.cpp
@@ -18,7 +18,7 @@
 
 #include <android/log.h>
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,"namespaceb",__VA_ARGS__)
 
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c b/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
index 3fda82a..cb44b42 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
+++ b/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
@@ -20,7 +20,7 @@
  */
 
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #include <stdbool.h>
 #include <string.h>
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_JniCTest.c b/tests/tests/jni/libjnitest/android_jni_cts_JniCTest.c
index 23278dc..cca5383 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_JniCTest.c
+++ b/tests/tests/jni/libjnitest/android_jni_cts_JniCTest.c
@@ -19,7 +19,7 @@
  */
 
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 
 /*
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_JniCppTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_JniCppTest.cpp
index 38829a0..b0937f4 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_JniCppTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_JniCppTest.cpp
@@ -19,7 +19,7 @@
  */
 
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 
 /*
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp
index 5e8bea0..aa5651f 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp
@@ -19,7 +19,7 @@
  */
 
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 extern "C" JNIEXPORT jint JNICALL Java_android_jni_cts_ClassLoaderHelper_nativeGetHashCode(
         JNIEnv* env,
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index c983ee2..748b756 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -22,7 +22,6 @@
 #include <dlfcn.h>
 #include <fcntl.h>
 #include <jni.h>
-#include <JNIHelp.h>
 #include <libgen.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -34,8 +33,9 @@
 #include <unordered_set>
 #include <vector>
 
-#include "ScopedLocalRef.h"
-#include "ScopedUtfChars.h"
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
 
 #if defined(__LP64__)
 static const std::string kSystemLibraryPath = "/system/lib64";
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c b/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
index ada2bf8..4e330e5 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
+++ b/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
@@ -20,7 +20,7 @@
  */
 
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #include <stdbool.h>
 #include <string.h>
diff --git a/tests/tests/jni/libjnitest/macroized_tests.c b/tests/tests/jni/libjnitest/macroized_tests.c
index 130b378..e8ac08f 100644
--- a/tests/tests/jni/libjnitest/macroized_tests.c
+++ b/tests/tests/jni/libjnitest/macroized_tests.c
@@ -182,13 +182,13 @@
 // TODO: Missing functions:
 //   AllocObject
 
-static char *help_CallBooleanMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallBooleanMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnBoolean", "()Z");
 
     if (method == NULL) {
@@ -287,13 +287,13 @@
     return help_CallBooleanMethod(env, STATIC_VA);
 }
 
-static char *help_CallByteMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallByteMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnByte", "()B");
 
     if (method == NULL) {
@@ -392,13 +392,13 @@
     return help_CallByteMethod(env, STATIC_VA);
 }
 
-static char *help_CallShortMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallShortMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnShort", "()S");
 
     if (method == NULL) {
@@ -497,13 +497,13 @@
     return help_CallShortMethod(env, STATIC_VA);
 }
 
-static char *help_CallCharMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallCharMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnChar", "()C");
 
     if (method == NULL) {
@@ -602,13 +602,13 @@
     return help_CallCharMethod(env, STATIC_VA);
 }
 
-static char *help_CallIntMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallIntMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnInt", "()I");
 
     if (method == NULL) {
@@ -707,13 +707,13 @@
     return help_CallIntMethod(env, STATIC_VA);
 }
 
-static char *help_CallLongMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallLongMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnLong", "()J");
 
     if (method == NULL) {
@@ -812,13 +812,13 @@
     return help_CallLongMethod(env, STATIC_VA);
 }
 
-static char *help_CallFloatMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallFloatMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnFloat", "()F");
 
     if (method == NULL) {
@@ -917,13 +917,13 @@
     return help_CallFloatMethod(env, STATIC_VA);
 }
 
-static char *help_CallDoubleMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallDoubleMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnDouble", "()D");
 
     if (method == NULL) {
@@ -1022,13 +1022,13 @@
     return help_CallDoubleMethod(env, STATIC_VA);
 }
 
-static char *help_CallVoidMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallVoidMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "nop", "()V");
 
     if (method == NULL) {
@@ -1127,13 +1127,13 @@
     return help_CallVoidMethod(env, STATIC_VA);
 }
 
-static char *help_CallObjectMethod(JNIEnv *env, callType ct, ...) {
+static char *help_CallObjectMethod(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "returnString", "()Ljava/lang/String;");
 
     if (method == NULL) {
@@ -1250,13 +1250,13 @@
     return help_CallObjectMethod(env, STATIC_VA);
 }
 
-static char *help_TakeOneOfEach(JNIEnv *env, callType ct, ...) {
+static char *help_TakeOneOfEach(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "takeOneOfEach", "(DFJICSBZLjava/lang/String;)Z");
 
     if (method == NULL) {
@@ -1372,13 +1372,13 @@
             (jboolean) true, biscuits);
 }
 
-static char *help_TakeCoolHandLuke(JNIEnv *env, callType ct, ...) {
+static char *help_TakeCoolHandLuke(JNIEnv *env, int ct, ...) {
     va_list args;
     va_start(args, ct);
 
     char *msg;
     jobject o = getStandardInstance(env);
-    jmethodID method = findAppropriateMethod(env, &msg, ct,
+    jmethodID method = findAppropriateMethod(env, &msg, (callType)ct,
             "takeCoolHandLuke",
             "(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z");
 
diff --git a/tests/tests/media/libmediandkjni/codec-utils-jni.cpp b/tests/tests/media/libmediandkjni/codec-utils-jni.cpp
index cb4363e..d7bd74e 100644
--- a/tests/tests/media/libmediandkjni/codec-utils-jni.cpp
+++ b/tests/tests/media/libmediandkjni/codec-utils-jni.cpp
@@ -24,8 +24,8 @@
 #include <sys/types.h>
 #include <jni.h>
 
-#include <ScopedLocalRef.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
 
 #include <math.h>
 
diff --git a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
index aa549b2..6cf9a89 100644
--- a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
@@ -24,7 +24,7 @@
 
 #include <assert.h>
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 
 #include <android/native_window_jni.h>
 
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
index 68f839c..01e1447 100644
--- a/tests/tests/os/jni/Android.mk
+++ b/tests/tests/os/jni/Android.mk
@@ -57,6 +57,14 @@
 endif
 
 LOCAL_CFLAGS := -Wno-unused-parameter
+
+# Let's overwrite -mcpu in case it's set to some ARMv8 core by
+# TARGET_2ND_CPU_VARIANT and causes clang to ignore the -march below.
 LOCAL_CPPFLAGS_arm := -mcpu=generic
 
+# The ARM version of this library must be built using ARMv7 ISA (even if it
+# can be run on armv8 cores) since one of the tested instruction, swp, is
+# only supported in ARMv7 (and older) cores, and obsolete in ARMv8.
+LOCAL_CPPFLAGS_arm += -march=armv7-a
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
index 0547be4..22dae69 100644
--- a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
+++ b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
@@ -25,9 +25,9 @@
 #include <grp.h>
 #include <pwd.h>
 #include <string.h>
-#include <ScopedLocalRef.h>
-#include <ScopedPrimitiveArray.h>
-#include <ScopedUtfChars.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
 
 static jfieldID gFileStatusDevFieldID;
 static jfieldID gFileStatusInoFieldID;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
index bc13144..cf535e8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
@@ -3045,9 +3045,9 @@
         RemquoResult expected = remquo(args.inNumerator, args.inDenominator);
         // If the expected remainder is NaN, we don't validate the quotient.  It's because of
         // a division by zero.
-        if (expected.remainder != expected.remainder) {
+        if (Float.isNaN(expected.remainder)) {
             // Check that the value we got is NaN too.
-            if (args.out == args.out) {
+            if (!Float.isNaN(args.out)) {
                 return "Expected a remainder of NaN but got " +  Float.toString(args.out);
             }
         } else {
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Target.java b/tests/tests/renderscript/src/android/renderscript/cts/Target.java
index 55d3712..3ac4ff8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/Target.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Target.java
@@ -341,7 +341,7 @@
             mHasRange = false;
             mValue = values[0];
             for (double f: values) {
-                if (f != f) {
+                if (Double.isNaN(f)) {
                     mCanBeNan = true;
                     continue;
                 }
@@ -573,7 +573,7 @@
         public boolean couldBe(double a, double extraAllowedError) {
             //Log.w("Floaty.couldBe", "Can " + Double.toString(a) + " be " + toString() + "? ");
             // Handle the input being a NaN.
-            if (a != a) {
+            if (Double.isNaN(a)) {
                 //Log.w("couldBe", "true because is Naan");
                 return mCanBeNan;
             }
diff --git a/tests/tests/rsblas/libbnnmdata/Android.mk b/tests/tests/rsblas/libbnnmdata/Android.mk
index bbfd289..84fb4e6 100644
--- a/tests/tests/rsblas/libbnnmdata/Android.mk
+++ b/tests/tests/rsblas/libbnnmdata/Android.mk
@@ -14,7 +14,6 @@
 
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_CLANG := true
 
 LOCAL_MODULE := libbnnmdata_jni
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/tests/rscpp/librscpptest/Android.mk b/tests/tests/rscpp/librscpptest/Android.mk
index 5621c02..47ab6dd3 100644
--- a/tests/tests/rscpp/librscpptest/Android.mk
+++ b/tests/tests/rscpp/librscpptest/Android.mk
@@ -18,7 +18,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_CLANG := true
 LOCAL_MODULE := librscpptest_jni
 LOCAL_MODULE_TAGS := optional
 
diff --git a/tests/tests/security/jni/android_security_cts_EncryptionTest.cpp b/tests/tests/security/jni/android_security_cts_EncryptionTest.cpp
index 136b52b..47f760a 100644
--- a/tests/tests/security/jni/android_security_cts_EncryptionTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_EncryptionTest.cpp
@@ -18,7 +18,7 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 #include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
 #include <openssl/aes.h>
 #include <openssl/cpu.h>
 #include <openssl/evp.h>
diff --git a/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp b/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
index 1cfde0a..c7975ec 100644
--- a/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
@@ -15,10 +15,10 @@
  */
 
 #include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include <selinux/selinux.h>
-#include <JNIHelp.h>
-#include <ScopedLocalRef.h>
-#include <ScopedUtfChars.h>
 
 #include <memory>
 
diff --git a/tests/tests/view/jni/Android.mk b/tests/tests/view/jni/Android.mk
index 288e250..f1aad68 100644
--- a/tests/tests/view/jni/Android.mk
+++ b/tests/tests/view/jni/Android.mk
@@ -32,6 +32,4 @@
 
 LOCAL_CXX_STL := libc++_static
 
-LOCAL_CLANG := true
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index c7d61e4..672ebe9 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -29,6 +29,7 @@
 include $(BUILD_JAVA_LIBRARY)
 
 cts-tf-dalvik-lib.jack := $(full_classes_jack)
+cts-tf-dalvik-lib.jar := $(full_classes_jar)
 
 # buildutil java library
 # ============================================================
@@ -80,6 +81,8 @@
 
 ifdef LOCAL_JACK_ENABLED
     vmteststf_dep_jars += $(cts-tf-dalvik-lib.jack)
+else
+    vmteststf_dep_jars += $(cts-tf-dalvik-lib.jar)
 endif
 
 $(LOCAL_BUILT_MODULE): PRIVATE_SRC_FOLDER := $(LOCAL_PATH)/src
@@ -91,23 +94,30 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_CLASS_PATH := $(call normalize-path-list, $(vmteststf_dep_jars))
 $(LOCAL_BUILT_MODULE): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
 ifndef LOCAL_JACK_ENABLED
+oj_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,core-oj,,COMMON)/classes.jar
+libart_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,core-libart,,COMMON)/classes.jar
+$(LOCAL_BUILT_MODULE): PRIVATE_DALVIK_SUITE_CLASSPATH := $(oj_jar):$(libart_jar):$(cts-tf-dalvik-lib.jar):$(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar:
 $(LOCAL_BUILT_MODULE) : $(vmteststf_dep_jars) $(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar
 	$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)
 	$(hide) mkdir -p $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/dot/junit $(dir $(PRIVATE_INTERMEDIATES_DEXCORE_JAR))
 	# generated and compile the host side junit tests
 	@echo "Write generated Main_*.java files to $(PRIVATE_INTERMEDIATES_MAIN_FILES)"
 	$(hide) $(JAVA) \
-	    $(if $(EXPERIMENTAL_USE_OPENJDK9),--add-exports jdk.jartool/sun.tools.jar=ALL-UNNAMED) \
 	    -cp $(PRIVATE_CLASS_PATH) util.build.BuildDalvikSuite $(PRIVATE_SRC_FOLDER) $(PRIVATE_INTERMEDIATES) \
-		$(HOST_OUT_JAVA_LIBRARIES)/cts-tf-dalvik-buildutil.jar:$(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar \
+		$(PRIVATE_DALVIK_SUITE_CLASSPATH) \
 		$(PRIVATE_INTERMEDIATES_MAIN_FILES) $(PRIVATE_INTERMEDIATES_CLASSES) $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES) $$RUN_VM_TESTS_RTO
 	@echo "Generate $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)"
-	$(hide) $(JAR) -cf $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar \
-		$(addprefix -C $(PRIVATE_INTERMEDIATES_CLASSES) , dot/junit/DxUtil.class dot/junit/DxAbstractMain.class)
-	$(hide) $(DX) -JXms16M -JXmx768M --dex --output=$(PRIVATE_INTERMEDIATES_DEXCORE_JAR) \
-		$(if $(NO_OPTIMIZE_DX), --no-optimize) $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar && rm -f $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar
-	$(hide) cd $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/classes && zip -q -r ../../$(notdir $@).jar .
+	$(hide) $(JAR) -cf $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar \
+		$(addprefix -C $(PRIVATE_INTERMEDIATES_CLASSES) , dot/junit/DxUtil.class dot/junit/DxAbstractMain.class dot/junit/AssertionFailedException.class)
+	$(hide) mkdir -p $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp
+	$(hide) $(if $(DX_ALT_JAR), $(JAVA) -Xms16M -Xmx768M -jar $(DX_ALT_JAR), $(DX) -JXms16M -JXmx768M) \
+		--dex --output=$(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp \
+		$(if $(NO_OPTIMIZE_DX), --no-optimize) $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar && rm -f $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar
+	$(hide) cd $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp && zip -q -r $(abspath $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)) .
+	$(hide) cd $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/classes && zip -q -r ../../$(notdir $@) .
 	$(hide) cd $(dir $@) && zip -q -r $(notdir $@) tests
+oj_jar :=
+libart_jar :=
 else # LOCAL_JACK_ENABLED
 oj_jack := $(call intermediates-dir-for,JAVA_LIBRARIES,core-oj,,COMMON)/classes.jack
 libart_jack := $(call intermediates-dir-for,JAVA_LIBRARIES,core-libart,,COMMON)/classes.jack
@@ -122,7 +132,7 @@
 		$(PRIVATE_INTERMEDIATES_MAIN_FILES) $(PRIVATE_INTERMEDIATES_CLASSES) $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES) $$RUN_VM_TESTS_RTO
 	@echo "Generate $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)"
 	$(hide) $(JAR) -cf $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar \
-		$(addprefix -C $(PRIVATE_INTERMEDIATES_CLASSES) , dot/junit/DxUtil.class dot/junit/DxAbstractMain.class)
+		$(addprefix -C $(PRIVATE_INTERMEDIATES_CLASSES) , dot/junit/DxUtil.class dot/junit/DxAbstractMain.class dot/junit/AssertionFailedException.class)
 	$(hide) $(call call-jack) --import $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar --output-jack $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jack
 	$(hide) mkdir -p $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp
 	$(hide) $(call call-jack,$(PRIVATE_JACK_EXTRA_ARGS)) --output-dex $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp \
diff --git a/tools/vm-tests-tf/etc/starthosttests b/tools/vm-tests-tf/etc/starthosttests
new file mode 100755
index 0000000..c1144f0
--- /dev/null
+++ b/tools/vm-tests-tf/etc/starthosttests
@@ -0,0 +1,249 @@
+#!/bin/bash
+#
+# Copyright (C) 2008 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+javaOpts=""
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+
+#######################################################################
+# Original content of invocation script follows. Uses values cleverly
+# deduced by the above code.
+#######################################################################
+
+selection=$1
+interpreter="fast"
+if [ "$selection" = "--portable" ]; then
+    selection=$2;
+    interpreter="portable"
+fi
+
+dalviktest=$ANDROID_BUILD_TOP/out/host/common/obj/JAVA_LIBRARIES/vm-tests-tf_intermediates
+dalviktestdir=$dalviktest/tests
+dexcore=$dalviktest/tests/dot/junit/dexcore.jar
+scriptdata=$dalviktestdir/data/scriptdata
+report=$dalviktest/report.html
+curdate=`date`
+datadir=/tmp/${USER}
+export ANDROID_PRINTF_LOG=tag
+export ANDROID_LOG_TAGS='*:s' # was: jdwp:i dalvikvm:i dalvikvmi:i'
+export ANDROID_DATA=$datadir
+export ANDROID_ROOT=$ANDROID_HOST_OUT
+# export LD_LIBRARY_PATH=$base/system/lib
+# export DYLD_LIBRARY_PATH=$base/system/lib
+debug_opts="-Xcheck:jni -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
+vmtpath=$ANDROID_HOST_OUT/../common/obj/JAVA_LIBRARIES/vm-tests-tf_intermediates/tests
+
+echo "--------------------------------------------------"
+echo "Dalvik VM Test Suite"
+echo "Version 1.0"
+echo "Copyright (c) 2008 The Android Open Source Project"
+echo ""
+
+if [ "$selection" = "--help" ]; then
+    echo "Usage: vm-tests [--help|--portable] [<mnemonic>]"
+    echo ""
+    echo "    --help      prints this help message"
+    echo ""
+    echo "    <mnemonic>  specifies the instruction to test;"
+    echo "                default is to run all tests"
+    echo ""
+    exit 1;
+fi
+
+rm -rf --preserve-root $datadir/dalvik-cache
+mkdir -p $datadir
+mkdir -p $datadir/dalvik-cache
+
+echo ""
+
+pre_report="<html><head><style>
+table tr.ok { background:#a0ffa0; }
+table tr.nok { background:#ffa0a0; }
+table tr.wok { background:#ffffa0; }
+table tr.lok { background:#aaaaff; }
+</style></head>
+<body>
+<h1>Dalvik VM test suite results</h1>
+Generated $curdate (using the emulator)
+<p>
+<table width='100%'>
+<tr><td>Status</td><td>Target</td><td>Category</td><td>Details</td></tr>"
+post_report="</body></html>"
+
+rm -f $report
+echo $pre_report > $report
+
+# ----------- running each opcode test ------------
+
+export jpassedcnt=0
+export jfailedcnt=0
+export jvfefailedcnt=0
+export jwarningcnt=0
+export jallcnt=0
+export jcolumns=0
+
+function classnameToJar()
+{
+    echo $1 | sed -e 's#\.#/#g;s#$#.jar#'
+}
+
+while read -u 3 myline;
+do
+    # dot.junit.opcodes.add_double.Main_testB1;dot.junit.opcodes.add_double.d.T_add_double_1 ;opcode add_double;test B #1 (border edge case)
+    # ->
+    # mainclass: dot.junit.opcodes.add_double.Main_testB1
+    # testcasedir: opcodes/add_double
+    # testname: testB1 ->
+    # dir dot/junit/opcodes/add_double/testB1
+
+    # e.g dot.junit.opcodes.add_double.Main_testB1
+    mainclass=`echo $myline | cut -d";" -f1`
+    # e.g dot.junit.opcodes.add_double.d.T_add_double_1, space sep. >=1 entries
+    deps=`echo $myline | cut -d";" -f2`
+
+    jtitle=`echo $myline | cut -d";" -f3`
+    jcomment=`echo $myline | cut -d";" -f4`
+    details=`echo $myline | cut -d";" -f5`
+
+    if [ "$selection" == "" ] || [ "$jtitle" == "$selection" ]; then
+
+        (( jallcnt += 1 ))
+
+        cd $dalviktestdir
+        rm -f $datadir/dalvikout
+        # write dalvik output to file
+        echo -n "mk_b:" > $datadir/dalvikout
+
+        classpath="${vmtpath}/dot/junit/dexcore.jar:${vmtpath}/mains.jar"
+        deps=${deps}" "${mainclass}
+        for dep in ${deps}; do
+            depJar=`classnameToJar ${dep}`
+            classpath=${classpath}:${vmtpath}/${depJar}
+        done
+
+        art -Djava.io.tmpdir=/tmp/${USER} \
+            -classpath $classpath $mainclass >> $datadir/dalvikout 2>&1 && \
+             echo -n dvmpassed: >> $datadir/dalvikout 2>&1
+
+        echo -n "mk_s:" >> $datadir/dalvikout
+        # Verify tmpout only contains mkdxc_start;mkdxc_stop -> no system.out/err
+        # because of exception. If ok -> green report line else red report with info
+        # between mkdxc_start and stop
+        vmresult=`cat $datadir/dalvikout`
+
+        if [[ ("$vmresult" == "mk_b:mk_s:") || ("$vmresult" == "mk_b:dvmpassed:mk_s:") ]]; then
+            (( jpassedcnt += 1 ))
+            echo -n "<tr class=\"ok\"><td>Success</td><td>$jtitle</td>" >> $report
+            echo "<td>$jcomment</td><td>$details</td></tr>" >> $report
+            echo -n "."
+        else
+            vmres=`cat $datadir/dalvikout | sed -e 's/mk_b://;s/mk_s://'`
+            vmres="$details<br><pre>$vmres</pre>"
+
+            stacktraces=`echo $vmresult | grep "java\.lang\." | grep -c "at dot\.junit\."`
+            if [[ $stacktraces > 0 ]]; then
+                jtype=`echo "$mainclass" | sed -e 's/.*_test\([^0-9]*\)[0-9].*/\1/' `
+                if [ "$jtype" == "VFE" ]; then
+                    (( jvfefailedcnt += 1 ))
+                    echo -n "V"
+                else
+                    (( jfailedcnt += 1 ))
+                    echo -n "F"
+                fi
+
+                echo "<tr class=\"nok\"><td>Failure</td><td>$jtitle</td><td>" >> $report
+                echo "$jcomment</td><td>$vmres</td></tr>" >> $report
+            else
+                (( jwarningcnt += 1 ))
+                echo "<tr class=\"wok\"><td>Failure</td><td>$jtitle</td><td>" >> $report
+                echo "$jcomment</td><td>(No stacktrace, but errors on console)" >> $report
+                echo "<br>$vmres</td></tr>" >> $report
+                echo -n "C"
+            fi
+        fi
+
+        (( jcolumns += 1 ))
+        if [ ${jcolumns} -eq 40 ]; then
+            echo ""
+            (( jcolumns = 0 ))
+        fi
+
+    fi
+# Use fd nr 3 to avoid subshelling via cat since this looses all
+# variables(and thus also the counters we are interested in).
+done 3<$scriptdata
+
+echo "</table>" >> $report
+let jallcalccnt=$jpassedcnt+$jfailedcnt+$jvfefailedcnt+$jwarningcnt
+if [ $jallcalccnt -ne $jallcnt ]; then
+    echo "<br>error: green & red != total , $jallcalccnt -ne $jallcnt" >> $report
+    exit 1;
+fi
+
+echo $post_report >> $report
+
+echo "<br>Tests run: ${jallcnt}" >> $report
+echo "<br>Functional failures: ${jfailedcnt}" >> $report
+echo "<br>Verifier failures: ${jvfefailedcnt}" >> $report
+echo "<br>Console errors: ${jwarningcnt}" >> $report
+
+echo $post_report >> $report
+
+if [[ jcolumns -ne 0 ]]; then
+    echo ""
+fi
+
+echo ""
+
+if [[ jallcnt -eq jpassedcnt ]]; then
+    echo "OK (${jpassedcnt} tests)"
+else
+    echo "FAILURES!!!"
+    echo ""
+    echo "Tests run          : ${jallcnt}"
+    echo "Functional failures: ${jfailedcnt}"
+    echo "Verifier failures  : ${jvfefailedcnt}"
+    echo "Console errors     : ${jwarningcnt}"
+fi
+
+echo ""
+echo "Please see complete report in ${report}"
+echo "--------------------------------------------------"
diff --git a/tools/vm-tests-tf/src/dot/junit/AssertionFailedException.java b/tools/vm-tests-tf/src/dot/junit/AssertionFailedException.java
new file mode 100644
index 0000000..44b686d
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/AssertionFailedException.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package dot.junit;
+
+class AssertionFailedException extends RuntimeException {
+
+    public AssertionFailedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public AssertionFailedException(String message) {
+        super(message);
+    }
+}
\ No newline at end of file
diff --git a/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java b/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
index dac6dcf..6223507 100644
--- a/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
+++ b/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
@@ -25,20 +25,19 @@
     private static void checkError(Class<?> expectedErrorClass, Throwable thrown,
                                    boolean in_invocation_exc) {
         if (expectedErrorClass != null && thrown == null) {
-            fail("Expected error of type " + expectedErrorClass);
+            fail("Expected error of type " + expectedErrorClass, null);
         } else if (expectedErrorClass == null && thrown != null) {
-            fail("Unexpected error " + thrown);
+            fail("Unexpected error " + thrown, thrown);
         } else if (expectedErrorClass != null && thrown != null) {
             if (in_invocation_exc) {
                 if (!(thrown instanceof java.lang.reflect.InvocationTargetException)) {
-                    fail("Expected invocation target exception, but got " + thrown);
+                    fail("Expected invocation target exception, but got " + thrown, thrown);
                 }
                 thrown = thrown.getCause();
             }
             if (!expectedErrorClass.equals(thrown.getClass())) {
-                thrown.printStackTrace(System.err);
                 fail("Expected error of type " + expectedErrorClass + ", but got " +
-                     thrown.getClass());
+                         thrown.getClass(), thrown);
             }
         }
     }
@@ -47,19 +46,19 @@
      * Try to load the class with the given name, and check for the expected error.
      */
     public static Class<?> load(String className, Class<?> expectedErrorClass) {
+        Class<?> c;
         try {
-            Class<?> c = Class.forName(className);
-            checkError(expectedErrorClass, null, false);
-            return c;
+            c = Class.forName(className);
         } catch (Throwable t) {
             if (expectedErrorClass != null) {
                 checkError(expectedErrorClass, t, false);
             } else {
-                t.printStackTrace(System.err);
-                fail("Could not load class " + className + ": " + t);
+                fail("Could not load class " + className, t);
             }
             return null;
         }
+        checkError(expectedErrorClass, null, false);
+        return c;
     }
 
     /**
@@ -80,7 +79,7 @@
             }
         }
         if (method == null) {
-            fail("Could not find method 'run'");
+            fail("Could not find method 'run'", null);
         }
 
         Object receiver = null;
@@ -88,16 +87,17 @@
             try {
                 receiver = c.newInstance();
             } catch (Exception exc) {
-                fail("Could not instantiate " + className + ": " + exc.getMessage());
+                fail("Could not instantiate " + className, exc);
             }
         }
 
         try {
             method.invoke(receiver, args);
-            checkError(expectedErrorClass, null, false);
         } catch (Throwable t) {
             checkError(expectedErrorClass, t, wrapped);
+            return;
         }
+        checkError(expectedErrorClass, null, false);
     }
 
     public static void loadAndRun(String className, Class<?> expectedErrorClass) {
@@ -109,19 +109,26 @@
     }
 
     static public void assertEquals(int expected, int actual) {
-        if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals. Expected " + expected + " actual " + actual);
+        if (expected != actual)
+            throw new AssertionFailedException(
+                    "not equals. Expected " + expected + " actual " + actual);
     }
 
     static public void assertEquals(String message, int expected, int actual) {
-        if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals: " + message + " Expected " + expected + " actual " + actual);
+        if (expected != actual)
+            throw new AssertionFailedException(
+                    "not equals: " + message + " Expected " + expected + " actual " + actual);
     }
 
     static public void assertEquals(long expected, long actual) {
-        if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals. Expected " + expected + " actual " + actual);
+        if (expected != actual)
+            throw new AssertionFailedException(
+                    "not equals. Expected " + expected + " actual " + actual);
     }
 
     static public void assertEquals(double expected, double actual, double delta) {
-        if(!(Math.abs(expected-actual) <= delta)) throw new RuntimeException("AssertionFailedError: not within delta");
+        if (!(Math.abs(expected - actual) <= delta))
+            throw new AssertionFailedException("not within delta");
     }
 
     static public void assertEquals(Object expected, Object actual) {
@@ -129,26 +136,34 @@
             return;
         if (expected != null && expected.equals(actual))
             return;
-        throw new RuntimeException("AssertionFailedError: not the same");
+        throw new AssertionFailedException("not the same: " + expected + " vs " + actual);
     }
 
     static public void assertTrue(boolean condition) {
-        if (!condition) throw new RuntimeException("AssertionFailedError: condition was false");
+        if (!condition)
+            throw new AssertionFailedException("condition was false");
     }
 
     static public void assertFalse(boolean condition) {
-        if (condition) throw new RuntimeException("AssertionFailedError: condition was true");
+        if (condition)
+            throw new AssertionFailedException("condition was true");
     }
 
     static public void assertNotNull(Object object) {
-        if (object == null) throw new RuntimeException("AssertionFailedError: object was null");
+        if (object == null)
+            throw new AssertionFailedException("object was null");
     }
 
     static public void assertNull(Object object) {
-        if (object != null) throw new RuntimeException("AssertionFailedError: object was not null");
+        if (object != null)
+            throw new AssertionFailedException("object was not null");
     }
 
     static public void fail(String message) {
-        throw new RuntimeException("AssertionFailedError msg:"+message);
+        fail(message, null);
+    }
+
+    static public void fail(String message, Throwable cause) {
+        throw new AssertionFailedException(message, cause);
     }
 }
diff --git a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
index a1cde1f..e551989 100644
--- a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
@@ -16,12 +16,18 @@
 
 package util.build;
 
-import com.sun.tools.javac.Main;
-
 import java.io.File;
-import java.io.PrintWriter;
+import java.lang.Iterable;
+import java.util.stream.Collectors;
+import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
 
 public class JavacBuildStep extends SourceBuildStep {
 
@@ -55,23 +61,37 @@
                 System.err.println("failed to create destination dir");
                 return false;
             }
-            int args = 8;
-            String[] commandLine = new String[sourceFiles.size()+args];
-            commandLine[0] = "-classpath";
-            commandLine[1] = classPath;
-            commandLine[2] = "-d";
-            commandLine[3] = destPath;
-            commandLine[4] = "-source";
-            commandLine[5] = "1.7";
-            commandLine[6] = "-target";
-            commandLine[7] = "1.7";
 
-            String[] files = new String[sourceFiles.size()];
-            sourceFiles.toArray(files);
+            Iterable<File> classPathFiles = Arrays.asList(classPath.split(":"))
+                    .stream()
+                    .map(File::new)
+                    .collect(Collectors.toList());
 
-            System.arraycopy(files, 0, commandLine, args, files.length);
+            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+            try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(
+                    null,     // diagnosticListener: we don't care about the details.
+                    null,     // locale: use default locale.
+                    null)) {  // charset: use platform default.
+                fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(
+                        new File(destPath)));
+                fileManager.setLocation(StandardLocation.CLASS_PATH, classPathFiles);
 
-            return Main.compile(commandLine, new PrintWriter(System.err)) == 0;
+                Iterable<? extends JavaFileObject> compilationUnits =
+                        fileManager.getJavaFileObjectsFromStrings(sourceFiles);
+
+                List<String> options = Arrays.asList("-source", "1.7", "-target", "1.7");
+
+                return compiler.getTask(
+                        null,  // out: write errors to System.err.
+                        fileManager,
+                        null,  // diagnosticListener: we don't care about the details.
+                        options,
+                        null,  // classes: classes for annotation processing = none.
+                        compilationUnits).call();
+            } catch (Exception e) {
+                e.printStackTrace();
+                return false;
+            }
         }
         return false;
     }