Merge changes Ia0623d38,Iaabd5d8b,I579bb12f,Ia9930edd

* changes:
  Fix splits class loader context for non dependant splits
  Encode the entire class loader context for dex2oat
  Add a command line option to optimize individual splits
  Refactor the arguments passed to dexopt invocations
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 88226f0..5e9b9ae3 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -43,6 +43,18 @@
     public native final double getDouble(long offset);
     public native final String getString(long offset);
 
+    /**
+      The copyTo... methods copy the blob's data, starting from the given
+      byte offset, into the array. A total of "size" _elements_ are copied.
+     */
+    public native final void copyToBoolArray(long offset, boolean[] array, int size);
+    public native final void copyToInt8Array(long offset, byte[] array, int size);
+    public native final void copyToInt16Array(long offset, short[] array, int size);
+    public native final void copyToInt32Array(long offset, int[] array, int size);
+    public native final void copyToInt64Array(long offset, long[] array, int size);
+    public native final void copyToFloatArray(long offset, float[] array, int size);
+    public native final void copyToDoubleArray(long offset, double[] array, int size);
+
     public native final void putBool(long offset, boolean x);
     public native final void putInt8(long offset, byte x);
     public native final void putInt16(long offset, short x);
@@ -52,6 +64,14 @@
     public native final void putDouble(long offset, double x);
     public native final void putString(long offset, String x);
 
+    public native final void putBoolArray(long offset, boolean[] x);
+    public native final void putInt8Array(long offset, byte[] x);
+    public native final void putInt16Array(long offset, short[] x);
+    public native final void putInt32Array(long offset, int[] x);
+    public native final void putInt64Array(long offset, long[] x);
+    public native final void putFloatArray(long offset, float[] x);
+    public native final void putDoubleArray(long offset, double[] x);
+
     public native final void putBlob(long offset, HwBlob blob);
 
     public native final long handle();
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index 40d49b7..737ec47 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -60,12 +60,12 @@
         JNIEnv *env, jobject thiz, const sp<JHwBlob> &context) {
     sp<JHwBlob> old = (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
 
-    if (context != NULL) {
-        context->incStrong(NULL /* id */);
+    if (context != nullptr) {
+        context->incStrong(nullptr /* id */);
     }
 
-    if (old != NULL) {
-        old->decStrong(NULL /* id */);
+    if (old != nullptr) {
+        old->decStrong(nullptr /* id */);
     }
 
     env->SetLongField(thiz, gFields.contextID, (long)context.get());
@@ -150,6 +150,10 @@
     return mBuffer;
 }
 
+void *JHwBlob::data() {
+    return mBuffer;
+}
+
 size_t JHwBlob::size() const {
     return mSize;
 }
@@ -242,8 +246,8 @@
 static void releaseNativeContext(void *nativeContext) {
     sp<JHwBlob> parcel = (JHwBlob *)nativeContext;
 
-    if (parcel != NULL) {
-        parcel->decStrong(NULL /* id */);
+    if (parcel != nullptr) {
+        parcel->decStrong(nullptr /* id */);
     }
 }
 
@@ -313,6 +317,82 @@
     return env->NewStringUTF(s->c_str());
 }
 
+#define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType)                          \
+static void JHwBlob_native_copyTo ## Suffix ## Array(                          \
+        JNIEnv *env,                                                           \
+        jobject thiz,                                                          \
+        jlong offset,                                                          \
+        Type ## Array array,                                                   \
+        jint size) {                                                           \
+    if (array == nullptr) {                                                    \
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);     \
+        return;                                                                \
+    }                                                                          \
+                                                                               \
+    if (env->GetArrayLength(array) < size) {                                   \
+        signalExceptionForError(env, BAD_VALUE);                               \
+        return;                                                                \
+    }                                                                          \
+                                                                               \
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
+                                                                               \
+    if ((offset + size * sizeof(Type)) > blob->size()) {                       \
+        signalExceptionForError(env, -ERANGE);                                 \
+        return;                                                                \
+    }                                                                          \
+                                                                               \
+    env->Set ## NewType ## ArrayRegion(                                        \
+            array,                                                             \
+            0 /* start */,                                                     \
+            size,                                                              \
+            reinterpret_cast<const Type *>(                                    \
+                static_cast<const uint8_t *>(blob->data()) + offset));         \
+}
+
+static void JHwBlob_native_copyToBoolArray(
+        JNIEnv *env,
+        jobject thiz,
+        jlong offset,
+        jbooleanArray array,
+        jint size) {
+    if (array == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    if (env->GetArrayLength(array) < size) {
+        signalExceptionForError(env, BAD_VALUE);
+        return;
+    }
+
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+    if ((offset + size * sizeof(bool)) > blob->size()) {
+        signalExceptionForError(env, -ERANGE);
+        return;
+    }
+
+    const bool *src =
+        reinterpret_cast<const bool *>(
+                static_cast<const uint8_t *>(blob->data()) + offset);
+
+    jboolean *dst = env->GetBooleanArrayElements(array, nullptr /* isCopy */);
+
+    for (jint i = 0; i < size; ++i) {
+        dst[i] = src[i];
+    }
+
+    env->ReleaseBooleanArrayElements(array, dst, 0 /* mode */);
+    dst = nullptr;
+}
+
+DEFINE_BLOB_ARRAY_COPIER(Int8,jbyte,Byte)
+DEFINE_BLOB_ARRAY_COPIER(Int16,jshort,Short)
+DEFINE_BLOB_ARRAY_COPIER(Int32,jint,Int)
+DEFINE_BLOB_ARRAY_COPIER(Int64,jlong,Long)
+DEFINE_BLOB_ARRAY_COPIER(Float,jfloat,Float)
+DEFINE_BLOB_ARRAY_COPIER(Double,jdouble,Double)
+
 #define DEFINE_BLOB_PUTTER(Suffix,Type)                                        \
 static void JHwBlob_native_put ## Suffix(                                      \
         JNIEnv *env, jobject thiz, jlong offset, Type x) {                     \
@@ -375,6 +455,72 @@
     blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
 }
 
+#define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType)                          \
+static void JHwBlob_native_put ## Suffix ## Array(                             \
+        JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) {        \
+                                                                               \
+    if (array == nullptr) {                                                    \
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);     \
+        return;                                                                \
+    }                                                                          \
+                                                                               \
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
+                                                                               \
+    jsize len = env->GetArrayLength(array);                                    \
+                                                                               \
+    Type *src =                                                                \
+        env->Get ## NewType ## ArrayElements(array, nullptr /* isCopy */);     \
+                                                                               \
+    status_t err = blob->write(offset, src, len * sizeof(Type));               \
+                                                                               \
+    env->Release ## NewType ## ArrayElements(array, src, 0 /* mode */);        \
+    src = nullptr;                                                             \
+                                                                               \
+    if (err != OK) {                                                           \
+        signalExceptionForError(env, err);                                     \
+    }                                                                          \
+}
+
+DEFINE_BLOB_ARRAY_PUTTER(Int8,jbyte,Byte)
+DEFINE_BLOB_ARRAY_PUTTER(Int16,jshort,Short)
+DEFINE_BLOB_ARRAY_PUTTER(Int32,jint,Int)
+DEFINE_BLOB_ARRAY_PUTTER(Int64,jlong,Long)
+DEFINE_BLOB_ARRAY_PUTTER(Float,jfloat,Float)
+DEFINE_BLOB_ARRAY_PUTTER(Double,jdouble,Double)
+
+static void JHwBlob_native_putBoolArray(
+        JNIEnv *env, jobject thiz, jlong offset, jbooleanArray array) {
+
+    if (array == nullptr) {
+        jniThrowException(env, "java/lang/NullPointerException", nullptr);
+        return;
+    }
+
+    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+    jsize len = env->GetArrayLength(array);
+
+    if ((offset + len * sizeof(bool)) > blob->size()) {
+        signalExceptionForError(env, -ERANGE);
+        return;
+    }
+
+    const jboolean *src =
+        env->GetBooleanArrayElements(array, nullptr /* isCopy */);
+
+    bool *dst = reinterpret_cast<bool *>(
+            static_cast<uint8_t *>(blob->data()) + offset);
+
+    for (jsize i = 0; i < len; ++i) {
+        dst[i] = src[i];
+    }
+
+    env->ReleaseBooleanArrayElements(
+            array, const_cast<jboolean *>(src), 0 /* mode */);
+
+    src = nullptr;
+}
+
 static void JHwBlob_native_putBlob(
         JNIEnv *env, jobject thiz, jlong offset, jobject blobObj) {
     if (blobObj == nullptr) {
@@ -413,6 +559,14 @@
     { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
     { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },
 
+    { "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray },
+    { "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array },
+    { "copyToInt16Array", "(J[SI)V", (void *)JHwBlob_native_copyToInt16Array },
+    { "copyToInt32Array", "(J[II)V", (void *)JHwBlob_native_copyToInt32Array },
+    { "copyToInt64Array", "(J[JI)V", (void *)JHwBlob_native_copyToInt64Array },
+    { "copyToFloatArray", "(J[FI)V", (void *)JHwBlob_native_copyToFloatArray },
+    { "copyToDoubleArray", "(J[DI)V", (void *)JHwBlob_native_copyToDoubleArray },
+
     { "putBool", "(JZ)V", (void *)JHwBlob_native_putBool },
     { "putInt8", "(JB)V", (void *)JHwBlob_native_putInt8 },
     { "putInt16", "(JS)V", (void *)JHwBlob_native_putInt16 },
@@ -422,6 +576,14 @@
     { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
     { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
 
+    { "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
+    { "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
+    { "putInt16Array", "(J[S)V", (void *)JHwBlob_native_putInt16Array },
+    { "putInt32Array", "(J[I)V", (void *)JHwBlob_native_putInt32Array },
+    { "putInt64Array", "(J[J)V", (void *)JHwBlob_native_putInt64Array },
+    { "putFloatArray", "(J[F)V", (void *)JHwBlob_native_putFloatArray },
+    { "putDoubleArray", "(J[D)V", (void *)JHwBlob_native_putDoubleArray },
+
     { "putBlob", "(JL" PACKAGE_PATH "/HwBlob;)V",
         (void *)JHwBlob_native_putBlob },
 
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 39393cb..6b1db63 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -50,6 +50,8 @@
             size_t offset, const android::hardware::hidl_string **s) const;
 
     const void *data() const;
+    void *data();
+
     size_t size() const;
 
     status_t putBlob(size_t offset, const sp<JHwBlob> &blob);