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

Commit 525f66fa authored by Oleg Petšjonkin's avatar Oleg Petšjonkin Committed by Automerger Merge Worker
Browse files

Merge changes I8c6764cc,Ia4bf8ad2 into udc-dev am: 43f5b64a

parents b8d9f125 43f5b64a
Loading
Loading
Loading
Loading
+27 −36
Original line number Diff line number Diff line
@@ -12,11 +12,11 @@ import android.util.Log;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * Describes the source of some work that may be done by someone else.
@@ -29,9 +29,13 @@ public class WorkSource implements Parcelable {

    @UnsupportedAppUsage
    int mNum;

    @UnsupportedAppUsage
    int[] mUids;
    @NonNull
    int[] mUids = new int[0];

    @UnsupportedAppUsage
    @Nullable
    String[] mNames;

    private ArrayList<WorkChain> mChains;
@@ -73,13 +77,8 @@ public class WorkSource implements Parcelable {
            return;
        }
        mNum = orig.mNum;
        if (orig.mUids != null) {
        mUids = orig.mUids.clone();
        mNames = orig.mNames != null ? orig.mNames.clone() : null;
        } else {
            mUids = null;
            mNames = null;
        }

        if (orig.mChains != null) {
            // Make a copy of all WorkChains that exist on |orig| since they are mutable.
@@ -114,7 +113,7 @@ public class WorkSource implements Parcelable {
     */
    @SystemApi
    public WorkSource(int uid, @NonNull String packageName) {
        Preconditions.checkNotNull(packageName, "packageName can't be null");
        Objects.requireNonNull(packageName, "packageName can't be null");
        mNum = 1;
        mUids = new int[] { uid, 0 };
        mNames = new String[] { packageName, null };
@@ -124,7 +123,7 @@ public class WorkSource implements Parcelable {
    @UnsupportedAppUsage
    WorkSource(Parcel in) {
        mNum = in.readInt();
        mUids = in.createIntArray();
        mUids = Objects.requireNonNullElse(in.createIntArray(), new int[0]);
        mNames = in.createStringArray();

        int numChains = in.readInt();
@@ -318,15 +317,11 @@ public class WorkSource implements Parcelable {
     */
    public void set(WorkSource other) {
        if (other == null) {
            mNum = 0;
            if (mChains != null) {
                mChains.clear();
            }
            clear();
            return;
        }
        mNum = other.mNum;
        if (other.mUids != null) {
            if (mUids != null && mUids.length >= mNum) {
        if (mUids.length >= mNum) { // this has more data than other
            System.arraycopy(other.mUids, 0, mUids, 0, mNum);
        } else {
            mUids = other.mUids.clone();
@@ -340,10 +335,6 @@ public class WorkSource implements Parcelable {
        } else {
            mNames = null;
        }
        } else {
            mUids = null;
            mNames = null;
        }

        if (other.mChains != null) {
            if (mChains != null) {
@@ -361,7 +352,7 @@ public class WorkSource implements Parcelable {
    /** @hide */
    public void set(int uid) {
        mNum = 1;
        if (mUids == null) mUids = new int[2];
        if (mUids.length == 0) mUids = new int[2];
        mUids[0] = uid;
        mNames = null;
        if (mChains != null) {
@@ -375,7 +366,7 @@ public class WorkSource implements Parcelable {
            throw new NullPointerException("Name can't be null");
        }
        mNum = 1;
        if (mUids == null) {
        if (mUids.length == 0) {
            mUids = new int[2];
            mNames = new String[2];
        }
@@ -727,7 +718,7 @@ public class WorkSource implements Parcelable {
                if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1
                        + ": insert " + uids2[i2]);
                changed = true;
                if (uids1 == null) {
                if (uids1.length == 0) {
                    uids1 = new int[4];
                    uids1[0] = uids2[i2];
                } else if (N1 >= uids1.length) {
@@ -866,7 +857,7 @@ public class WorkSource implements Parcelable {

    private void insert(int index, int uid)  {
        if (DEBUG) Log.d(TAG, "Insert in " + this + " @ " + index + " uid " + uid);
        if (mUids == null) {
        if (mUids.length == 0) {
            mUids = new int[4];
            mUids[0] = uid;
            mNum = 1;
@@ -891,7 +882,7 @@ public class WorkSource implements Parcelable {
    }

    private void insert(int index, int uid, String name)  {
        if (mUids == null) {
        if (mNum == 0) {
            mUids = new int[4];
            mUids[0] = uid;
            mNames = new String[4];
@@ -1244,8 +1235,8 @@ public class WorkSource implements Parcelable {
        proto.end(workSourceToken);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<WorkSource> CREATOR
            = new Parcelable.Creator<WorkSource>() {
    @NonNull
    public static final Parcelable.Creator<WorkSource> CREATOR = new Parcelable.Creator<>() {
        public WorkSource createFromParcel(Parcel in) {
            return new WorkSource(in);
        }
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ android_test {
    ],
    jni_libs: [
        "libpowermanagertest_jni",
        "libworksourceparceltest_jni",
    ],

    sdk_version: "core_platform",
+24 −0
Original line number Diff line number Diff line
@@ -43,3 +43,27 @@ cc_test_library {
    ],
    gtest: false,
}

cc_test_library {
    name: "libworksourceparceltest_jni",
    srcs: [
        "NativeWorkSourceParcelTest.cpp",
    ],
    shared_libs: [
        "libandroid",
        "libandroid_runtime_lazy",
        "libbase",
        "libbinder",
        "liblog",
        "libnativehelper",
        "libpowermanager",
        "libutils",
    ],
    header_libs: ["jni_headers"],
    stl: "libc++_static",
    cflags: [
        "-Werror",
        "-Wall",
    ],
    gtest: false,
}
+32 −140
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define LOG_TAG "NativePowerManagerTest"

#include "jni.h"
#include "ParcelHelper.h"

#include <android_util_Binder.h>
#include <binder/IServiceManager.h>
@@ -36,21 +37,6 @@ using android::base::StringPrintf;

namespace android {

#define FIND_CLASS(var, className) \
    var = env->FindClass(className); \
    LOG_FATAL_IF(!(var), "Unable to find class %s", className);

#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
    var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
    LOG_FATAL_IF(!(var), "Unable to find field %s", fieldName);

#define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
    var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
    LOG_FATAL_IF(!(var), "Unable to find method %s", fieldName);

static jclass gParcelClazz;
static jfieldID gParcelDataFieldID;
static jmethodID gParcelObtainMethodID;
static struct BatterySaverPolicyConfigFieldId {
    jfieldID adjustBrightnessFactor;
    jfieldID advertiseIsEnabled;
@@ -73,102 +59,6 @@ static struct BatterySaverPolicyConfigFieldId {
    jfieldID soundTriggerMode;
} gBSPCFieldIds;

static jobject nativeObtainParcel(JNIEnv* env) {
    jobject parcel = env->CallStaticObjectMethod(gParcelClazz, gParcelObtainMethodID);
    if (parcel == nullptr) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Obtain parcel failed.");
    }
    return parcel;
}

static Parcel* nativeGetParcelData(JNIEnv* env, jobject obj) {
    Parcel* parcel = reinterpret_cast<Parcel*>(env->GetLongField(obj, gParcelDataFieldID));
    if (parcel && parcel->objectsCount() != 0) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid parcel object.");
    }
    parcel->setDataPosition(0);
    return parcel;
}

static jobject nativeObtainWorkSourceParcel(JNIEnv* env, jobject /* obj */, jintArray uidArray,
            jobjectArray nameArray) {
    std::vector<int32_t> uids;
    std::optional<std::vector<std::optional<String16>>> names = std::nullopt;

    if (uidArray != nullptr) {
        jint *ptr = env->GetIntArrayElements(uidArray, 0);
        for (jint i = 0; i < env->GetArrayLength(uidArray); i++) {
            uids.push_back(static_cast<int32_t>(ptr[i]));
        }
    }

    if (nameArray != nullptr) {
        std::vector<std::optional<String16>> namesVec;
        for (jint i = 0; i < env->GetArrayLength(nameArray); i++) {
            jstring string = (jstring) (env->GetObjectArrayElement(nameArray, i));
            const char *rawString = env->GetStringUTFChars(string, 0);
            namesVec.push_back(std::make_optional<String16>(String16(rawString)));
        }
        names = std::make_optional(std::move(namesVec));
    }

    WorkSource ws = WorkSource(uids, names);
    jobject wsParcel = nativeObtainParcel(env);
    Parcel* parcel = nativeGetParcelData(env, wsParcel);
    status_t err = ws.writeToParcel(parcel);
    if (err != OK) {
        jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource writeToParcel failed %d", err).c_str());
    }
    parcel->setDataPosition(0);
    return wsParcel;
}

static void nativeUnparcelAndVerifyWorkSource(JNIEnv* env, jobject /* obj */, jobject wsParcel,
        jintArray uidArray, jobjectArray nameArray) {
    WorkSource ws = {};
    Parcel* parcel = nativeGetParcelData(env, wsParcel);

    status_t err = ws.readFromParcel(parcel);
    if (err != OK) {
        ALOGE("WorkSource writeToParcel failed %d", err);
    }

    // Now we have a native WorkSource object, verify it.
    if (uidArray != nullptr) {
        jint *ptr = env->GetIntArrayElements(uidArray, 0);
        for (jint i = 0; i < env->GetArrayLength(uidArray); i++) {
            if (ws.getUids().at(i) != static_cast<int32_t>(ptr[i])) {
                jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource uid not equal %d %d",
                            ws.getUids().at(i), static_cast<int32_t>(ptr[i])).c_str());
            }
        }
    } else {
        if (ws.getUids().size() != 0) {
            jniThrowException(env, "java/lang/IllegalArgumentException",
                    StringPrintf("WorkSource parcel size not 0").c_str());
        }
    }

    if (nameArray != nullptr) {
        std::vector<std::optional<String16>> namesVec;
        for (jint i = 0; i < env->GetArrayLength(nameArray); i++) {
            jstring string = (jstring) (env->GetObjectArrayElement(nameArray, i));
            const char *rawString = env->GetStringUTFChars(string, 0);
            if (String16(rawString) != ws.getNames()->at(i)) {
                jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource uid not equal %s", rawString).c_str());
            }
        }
    } else {
        if (ws.getNames() != std::nullopt) {
            jniThrowException(env, "java/lang/IllegalArgumentException",
                    StringPrintf("WorkSource parcel name not empty").c_str());
        }
    }
}

static jobject nativeObtainPowerSaveStateParcel(JNIEnv* env, jobject /* obj */,
        jboolean batterySaverEnabled, jboolean globalBatterySaverEnabled,
        jint locationMode, jint soundTriggerMode, jfloat brightnessFactor) {
@@ -305,10 +195,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
    JNIEnv* env;
    const JNINativeMethod methodTable[] = {
        /* name, signature, funcPtr */
        { "nativeObtainWorkSourceParcel", "([I[Ljava/lang/String;)Landroid/os/Parcel;",
                (void*) nativeObtainWorkSourceParcel },
        { "nativeUnparcelAndVerifyWorkSource", "(Landroid/os/Parcel;[I[Ljava/lang/String;)V",
                (void*) nativeUnparcelAndVerifyWorkSource },
        { "nativeObtainPowerSaveStateParcel", "(ZZIIF)Landroid/os/Parcel;",
                (void*) nativeObtainPowerSaveStateParcel },
        { "nativeUnparcelAndVerifyPowerSaveState", "(Landroid/os/Parcel;ZZIIF)V",
@@ -327,34 +213,40 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
        return JNI_ERR;
    }

    jclass bspcClazz;
    FIND_CLASS(gParcelClazz, "android/os/Parcel");
    GET_FIELD_ID(gParcelDataFieldID, gParcelClazz, "mNativePtr", "J");
    GET_STATIC_METHOD_ID(gParcelObtainMethodID, gParcelClazz, "obtain", "()Landroid/os/Parcel;");
    FIND_CLASS(bspcClazz, "android/os/BatterySaverPolicyConfig");
    GET_FIELD_ID(gBSPCFieldIds.adjustBrightnessFactor, bspcClazz, "mAdjustBrightnessFactor", "F");
    GET_FIELD_ID(gBSPCFieldIds.advertiseIsEnabled, bspcClazz, "mAdvertiseIsEnabled", "Z");
    GET_FIELD_ID(gBSPCFieldIds.deferFullBackup, bspcClazz, "mDeferFullBackup", "Z");
    GET_FIELD_ID(gBSPCFieldIds.deferKeyValueBackup, bspcClazz, "mDeferKeyValueBackup", "Z");
    GET_FIELD_ID(gBSPCFieldIds.deviceSpecificSettings, bspcClazz, "mDeviceSpecificSettings",
                    "Ljava/util/Map;");
    GET_FIELD_ID(gBSPCFieldIds.disableAnimation, bspcClazz, "mDisableAnimation", "Z");
    GET_FIELD_ID(gBSPCFieldIds.disableAod, bspcClazz, "mDisableAod", "Z");
    GET_FIELD_ID(gBSPCFieldIds.disableLaunchBoost, bspcClazz, "mDisableLaunchBoost", "Z");
    GET_FIELD_ID(gBSPCFieldIds.disableOptionalSensors, bspcClazz, "mDisableOptionalSensors", "Z");
    GET_FIELD_ID(gBSPCFieldIds.disableVibration, bspcClazz, "mDisableVibration", "Z");
    GET_FIELD_ID(gBSPCFieldIds.enableAdjustBrightness, bspcClazz, "mEnableAdjustBrightness", "Z");
    GET_FIELD_ID(gBSPCFieldIds.enableDataSaver, bspcClazz, "mEnableDataSaver", "Z");
    GET_FIELD_ID(gBSPCFieldIds.enableFirewall, bspcClazz, "mEnableFirewall", "Z");
    GET_FIELD_ID(gBSPCFieldIds.enableNightMode, bspcClazz, "mEnableNightMode", "Z");
    GET_FIELD_ID(gBSPCFieldIds.enableQuickDoze, bspcClazz, "mEnableQuickDoze", "Z");
    GET_FIELD_ID(gBSPCFieldIds.forceAllAppsStandby, bspcClazz, "mForceAllAppsStandby", "Z");
    GET_FIELD_ID(gBSPCFieldIds.forceBackgroundCheck, bspcClazz, "mForceBackgroundCheck", "Z");
    GET_FIELD_ID(gBSPCFieldIds.locationMode, bspcClazz, "mLocationMode", "I");
    GET_FIELD_ID(gBSPCFieldIds.soundTriggerMode, bspcClazz, "mSoundTriggerMode", "I");
    loadParcelClass(env);

    jclass bspcClazz = FindClassOrDie(env, "android/os/BatterySaverPolicyConfig");

    gBSPCFieldIds.adjustBrightnessFactor =
            GetFieldIDOrDie(env, bspcClazz, "mAdjustBrightnessFactor", "F");
    gBSPCFieldIds.advertiseIsEnabled = GetFieldIDOrDie(env, bspcClazz, "mAdvertiseIsEnabled", "Z");
    gBSPCFieldIds.deferFullBackup = GetFieldIDOrDie(env, bspcClazz, "mDeferFullBackup", "Z");
    gBSPCFieldIds.deferKeyValueBackup =
            GetFieldIDOrDie(env, bspcClazz, "mDeferKeyValueBackup", "Z");
    gBSPCFieldIds.deviceSpecificSettings =
            GetFieldIDOrDie(env, bspcClazz, "mDeviceSpecificSettings", "Ljava/util/Map;");
    gBSPCFieldIds.disableAnimation = GetFieldIDOrDie(env, bspcClazz, "mDisableAnimation", "Z");
    gBSPCFieldIds.disableAod = GetFieldIDOrDie(env, bspcClazz, "mDisableAod", "Z");
    gBSPCFieldIds.disableLaunchBoost = GetFieldIDOrDie(env, bspcClazz, "mDisableLaunchBoost", "Z");
    gBSPCFieldIds.disableOptionalSensors =
            GetFieldIDOrDie(env, bspcClazz, "mDisableOptionalSensors", "Z");
    gBSPCFieldIds.disableVibration = GetFieldIDOrDie(env, bspcClazz, "mDisableVibration", "Z");
    gBSPCFieldIds.enableAdjustBrightness =
            GetFieldIDOrDie(env, bspcClazz, "mEnableAdjustBrightness", "Z");
    gBSPCFieldIds.enableDataSaver = GetFieldIDOrDie(env, bspcClazz, "mEnableDataSaver", "Z");
    gBSPCFieldIds.enableFirewall = GetFieldIDOrDie(env, bspcClazz, "mEnableFirewall", "Z");
    gBSPCFieldIds.enableNightMode = GetFieldIDOrDie(env, bspcClazz, "mEnableNightMode", "Z");
    gBSPCFieldIds.enableQuickDoze = GetFieldIDOrDie(env, bspcClazz, "mEnableQuickDoze", "Z");
    gBSPCFieldIds.forceAllAppsStandby =
            GetFieldIDOrDie(env, bspcClazz, "mForceAllAppsStandby", "Z");
    gBSPCFieldIds.forceBackgroundCheck =
            GetFieldIDOrDie(env, bspcClazz, "mForceBackgroundCheck", "Z");
    gBSPCFieldIds.locationMode = GetFieldIDOrDie(env, bspcClazz, "mLocationMode", "I");
    gBSPCFieldIds.soundTriggerMode = GetFieldIDOrDie(env, bspcClazz, "mSoundTriggerMode", "I");

    jniRegisterNativeMethods(env, "android/os/PowerManagerTest", methodTable,
                sizeof(methodTable) / sizeof(JNINativeMethod));

    return JNI_VERSION_1_6;
}

+156 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "NativeWorkSourceParcelTest"

#include "jni.h"
#include "ParcelHelper.h"

#include <android_util_Binder.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <utils/Log.h>

#include <android/WorkSource.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

using namespace android::os;
using android::base::StringPrintf;

namespace android {

static jobject nativeObtainWorkSourceParcel(JNIEnv* env, jobject /* obj */, jintArray uidArray,
            jobjectArray nameArray, jint parcelEndMarker) {
    std::vector<int32_t> uids;
    std::optional<std::vector<std::optional<String16>>> names = std::nullopt;

    if (uidArray != nullptr) {
        ScopedIntArrayRO workSourceUids(env, uidArray);
        for (int i = 0; i < workSourceUids.size(); i++) {
            uids.push_back(static_cast<int32_t>(workSourceUids[i]));
        }
    }

    if (nameArray != nullptr) {
        std::vector<std::optional<String16>> namesVec;
        for (jint i = 0; i < env->GetArrayLength(nameArray); i++) {
            jstring string = static_cast<jstring>(env->GetObjectArrayElement(nameArray, i));
            const char *rawString = env->GetStringUTFChars(string, 0);
            namesVec.push_back(std::make_optional<String16>(String16(rawString)));
        }
        names = std::make_optional(std::move(namesVec));
    }

    WorkSource ws = WorkSource(uids, names);
    jobject wsParcel = nativeObtainParcel(env);
    Parcel* parcel = nativeGetParcelData(env, wsParcel);

    // write WorkSource and if no error write end marker
    status_t err = ws.writeToParcel(parcel) ?: parcel->writeInt32(parcelEndMarker);

    if (err != OK) {
        jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource writeToParcel failed %d", err).c_str());
    }
    parcel->setDataPosition(0);
    return wsParcel;
}

static void nativeUnparcelAndVerifyWorkSource(JNIEnv* env, jobject /* obj */, jobject wsParcel,
        jintArray uidArray, jobjectArray nameArray, jint parcelEndMarker) {
    WorkSource ws = {};
    Parcel* parcel = nativeGetParcelData(env, wsParcel);
    int32_t endMarker;

    // read WorkSource and if no error read end marker
    status_t err = ws.readFromParcel(parcel) ?: parcel->readInt32(&endMarker);
    int32_t dataAvailable = parcel->dataAvail();

    if (err != OK) {
        ALOGE("WorkSource readFromParcel failed %d", err);
    }

    // Now we have a native WorkSource object, verify it.
    if (dataAvailable > 0) { // not all data read from the parcel
        jniThrowException(env, "java/lang/IllegalArgumentException",
                StringPrintf("WorkSource contains more data than native read (%d)",
                dataAvailable).c_str());
    } else if (endMarker != parcelEndMarker) { // more date than available read from parcel
        jniThrowException(env, "java/lang/IllegalArgumentException",
                StringPrintf("WorkSource contains less data than native read").c_str());
    }

    if (uidArray != nullptr) {
        ScopedIntArrayRO workSourceUids(env, uidArray);
        for (int i = 0; i < workSourceUids.size(); i++) {
            if (ws.getUids().at(i) != static_cast<int32_t>(workSourceUids[i])) {
                jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource uid not equal %d %d",
                            ws.getUids().at(i), static_cast<int32_t>(workSourceUids[i])).c_str());
            }
        }
    } else {
        if (ws.getUids().size() != 0) {
            jniThrowException(env, "java/lang/IllegalArgumentException",
                    StringPrintf("WorkSource parcel size not 0").c_str());
        }
    }

    if (nameArray != nullptr) {
        std::vector<std::optional<String16>> namesVec;
        for (jint i = 0; i < env->GetArrayLength(nameArray); i++) {
            jstring string = (jstring) (env->GetObjectArrayElement(nameArray, i));
            const char *rawString = env->GetStringUTFChars(string, 0);
            if (String16(rawString) != ws.getNames()->at(i)) {
                jniThrowException(env, "java/lang/IllegalArgumentException",
                            StringPrintf("WorkSource uid not equal %s", rawString).c_str());
            }
        }
    } else {
        if (ws.getNames() != std::nullopt) {
            jniThrowException(env, "java/lang/IllegalArgumentException",
                    StringPrintf("WorkSource parcel name not empty").c_str());
        }
    }
}

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
    JNIEnv* env;

    const JNINativeMethod workSourceMethodTable[] = {
        /* name, signature, funcPtr */
        { "nativeObtainWorkSourceParcel", "([I[Ljava/lang/String;I)Landroid/os/Parcel;",
                (void*) nativeObtainWorkSourceParcel },
        { "nativeUnparcelAndVerifyWorkSource", "(Landroid/os/Parcel;[I[Ljava/lang/String;I)V",
                (void*) nativeUnparcelAndVerifyWorkSource },
    };

    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

    loadParcelClass(env);

    jniRegisterNativeMethods(env, "android/os/WorkSourceParcelTest", workSourceMethodTable,
                sizeof(workSourceMethodTable) / sizeof(JNINativeMethod));

    return JNI_VERSION_1_6;
}

} /* namespace android */
Loading