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

Commit 84b49130 authored by Paul McLean's avatar Paul McLean Committed by Eric Laurent
Browse files

Moving native MIDI JNI init to AndroidRuntime.cpp.

Remove (non-working) lazy init in midi.cpp

Bug: 79464070
Test: Verify function with NativeMidiTestbed app.
Change-Id: I30182d19d205b4ab952d622824f1a63ab1fef72e
parent 3a20be78
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ cc_library_shared {
        "android_media_JetPlayer.cpp",
        "android_media_MediaMetricsJNI.cpp",
        "android_media_MicrophoneInfo.cpp",
        "android_media_midi.cpp",
        "android_media_RemoteDisplay.cpp",
        "android_media_ToneGenerator.cpp",
        "android_hardware_Camera.cpp",
+2 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ extern int register_android_media_AudioTrack(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
extern int register_android_media_midi(JNIEnv *env);

namespace android {

@@ -1441,6 +1442,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_media_MicrophoneInfo),
    REG_JNI(register_android_media_RemoteDisplay),
    REG_JNI(register_android_media_ToneGenerator),
    REG_JNI(register_android_media_midi),

    REG_JNI(register_android_opengl_classes),
    REG_JNI(register_android_server_NetworkManagementSocketTagger),
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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_TAG "NativeMIDI_JNI"

#include <core_jni_helpers.h>

namespace android { namespace midi {
//  MidiDevice Fields
static jobject gMidiDeviceClassGlobalRef = nullptr;     // A GlobalRef for MidiDevice Class
jfieldID gFidMidiNativeHandle = nullptr;         // MidiDevice.mNativeHandle
jfieldID gFidMidiDeviceServerBinder = nullptr;   // MidiDevice.mDeviceServerBinder
jfieldID gFidMidiDeviceInfo = nullptr;           // MidiDevice.mDeviceInfo

//  MidiDeviceInfo Fields
static jobject gMidiDeviceInfoClassGlobalRef = nullptr; // A GlobalRef for MidiDeviceInfoClass
jfieldID mFidMidiDeviceId = nullptr;             // MidiDeviceInfo.mId
}}

using namespace android::midi;

int register_android_media_midi(JNIEnv *env) {
    jclass deviceClass = android::FindClassOrDie(env, "android/media/midi/MidiDevice");
    gMidiDeviceClassGlobalRef = env->NewGlobalRef(deviceClass);

    // MidiDevice Field IDs
    gFidMidiNativeHandle = android::GetFieldIDOrDie(env, deviceClass, "mNativeHandle", "J");
    gFidMidiDeviceServerBinder = android::GetFieldIDOrDie(env, deviceClass,
            "mDeviceServerBinder", "Landroid/os/IBinder;");
    gFidMidiDeviceInfo = android::GetFieldIDOrDie(env, deviceClass,
            "mDeviceInfo", "Landroid/media/midi/MidiDeviceInfo;");

    // MidiDeviceInfo Field IDs
    jclass deviceInfoClass = android::FindClassOrDie(env, "android/media/midi/MidiDeviceInfo");
    gMidiDeviceInfoClassGlobalRef = env->NewGlobalRef(deviceInfoClass);
    mFidMidiDeviceId = android::GetFieldIDOrDie(env, deviceInfoClass, "mId", "I");

    return 0;
}
+15 −37
Original line number Diff line number Diff line
@@ -87,37 +87,20 @@ enum {
#define AMIDI_PACKET_OVERHEAD   9
#define AMIDI_BUFFER_SIZE       (AMIDI_PACKET_SIZE - AMIDI_PACKET_OVERHEAD)

// JNI IDs (see android_media_midi.cpp)
namespace android { namespace midi {
//  MidiDevice Fields
static jobject deviceClassGlobalRef = nullptr;     // A GlobalRef for MidiDevice Class
static jfieldID fidDeviceClosed = nullptr;         // MidiDevice.mIsDeviceClosed
static jfieldID fidNativeHandle = nullptr;         // MidiDevice.mNativeHandle
static jfieldID fidDeviceServerBinder = nullptr;   // MidiDevice.mDeviceServerBinder
static jfieldID fidDeviceInfo = nullptr;           // MidiDevice.mDeviceInfo
extern jfieldID gFidMidiNativeHandle;         // MidiDevice.mNativeHandle
extern jfieldID gFidMidiDeviceServerBinder;   // MidiDevice.mDeviceServerBinder
extern jfieldID gFidMidiDeviceInfo;           // MidiDevice.mDeviceInfo

//  MidiDeviceInfo Fields
static jobject deviceInfoClassGlobalRef = nullptr; // A GlobalRef for MidiDeviceInfoClass
static jfieldID fidDeviceId = nullptr;             // MidiDeviceInfo.mId
extern jfieldID mFidMidiDeviceId;             // MidiDeviceInfo.mId
}}
using namespace android::midi;

static std::mutex openMutex; // Ensure that the device can be connected just once to 1 thread

static void AMIDI_initJNI(JNIEnv *env) {
    jclass deviceClass = android::FindClassOrDie(env, "android/media/midi/MidiDevice");
    deviceClassGlobalRef = env->NewGlobalRef(deviceClass);

    // MidiDevice Field IDs
    fidDeviceClosed = android::GetFieldIDOrDie(env, deviceClass, "mIsDeviceClosed", "Z");
    fidNativeHandle = android::GetFieldIDOrDie(env, deviceClass, "mNativeHandle", "J");
    fidDeviceServerBinder = android::GetFieldIDOrDie(env, deviceClass,
            "mDeviceServerBinder", "Landroid/os/IBinder;");
    fidDeviceInfo = android::GetFieldIDOrDie(env, deviceClass,
            "mDeviceInfo", "Landroid/media/midi/MidiDeviceInfo;");

    // MidiDeviceInfo Field IDs
    jclass deviceInfoClass = android::FindClassOrDie(env, "android/media/midi/MidiDeviceInfo");
    deviceInfoClassGlobalRef = env->NewGlobalRef(deviceInfoClass);
    fidDeviceId = android::GetFieldIDOrDie(env, deviceInfoClass, "mId", "I");
}

//// Handy debugging function.
//static void AMIDI_logBuffer(const uint8_t *data, size_t numBytes) {
//    for (size_t index = 0; index < numBytes; index++) {
@@ -162,10 +145,6 @@ static media_status_t AMIDI_API AMIDI_getDeviceInfo(const AMidiDevice *device,
media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
        AMidiDevice** devicePtrPtr)
{
    // Ensures JNI initialization is performed just once.
    static std::once_flag initCallFlag;
    std::call_once(initCallFlag, AMIDI_initJNI, env);

    if (j_midiDeviceObj == nullptr) {
        ALOGE("AMidiDevice_fromJava() invalid MidiDevice object.");
        return AMEDIA_ERROR_INVALID_OBJECT;
@@ -174,13 +153,13 @@ media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceO
    {
        std::lock_guard<std::mutex> guard(openMutex);

        long handle = env->GetLongField(j_midiDeviceObj, fidNativeHandle);
        long handle = env->GetLongField(j_midiDeviceObj, gFidMidiNativeHandle);
        if (handle != 0) {
            // Already opened by someone.
            return AMEDIA_ERROR_INVALID_OBJECT;
        }

        jobject serverBinderObj = env->GetObjectField(j_midiDeviceObj, fidDeviceServerBinder);
        jobject serverBinderObj = env->GetObjectField(j_midiDeviceObj, gFidMidiDeviceServerBinder);
        sp<IBinder> serverBinder = android::ibinderForJavaObject(env, serverBinderObj);
        if (serverBinder.get() == nullptr) {
            ALOGE("AMidiDevice_fromJava couldn't connect to native MIDI server.");
@@ -190,11 +169,11 @@ media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceO
        // don't check allocation failures, just abort..
        AMidiDevice* devicePtr = new AMidiDevice;
        devicePtr->server = new BpMidiDeviceServer(serverBinder);
        jobject midiDeviceInfoObj = env->GetObjectField(j_midiDeviceObj, fidDeviceInfo);
        devicePtr->deviceId = env->GetIntField(midiDeviceInfoObj, fidDeviceId);
        jobject midiDeviceInfoObj = env->GetObjectField(j_midiDeviceObj, gFidMidiDeviceInfo);
        devicePtr->deviceId = env->GetIntField(midiDeviceInfoObj, mFidMidiDeviceId);

        // Synchronize with the associated Java MidiDevice.
        env->SetLongField(j_midiDeviceObj, fidNativeHandle, (long)devicePtr);
        env->SetLongField(j_midiDeviceObj, gFidMidiNativeHandle, (long)devicePtr);
        env->GetJavaVM(&devicePtr->javaVM);
        devicePtr->midiDeviceObj = env->NewGlobalRef(j_midiDeviceObj);

@@ -220,17 +199,16 @@ media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device)
    LOG_ALWAYS_FATAL_IF(err != JNI_OK, "AMidiDevice_release Error accessing JNIEnv err:%d", err);

    // Synchronize with the associated Java MidiDevice.
    // env->CallVoidMethod(j_midiDeviceObj, midClearNativeHandle);
    {
        std::lock_guard<std::mutex> guard(openMutex);
        long handle = env->GetLongField(device->midiDeviceObj, fidNativeHandle);
        long handle = env->GetLongField(device->midiDeviceObj, gFidMidiNativeHandle);
        if (handle == 0) {
            // Not opened as native.
            ALOGE("AMidiDevice_release() device not opened in native client.");
            return AMEDIA_ERROR_INVALID_OBJECT;
        }

        env->SetLongField(device->midiDeviceObj, fidNativeHandle, 0L);
        env->SetLongField(device->midiDeviceObj, gFidMidiNativeHandle, 0L);
    }
    env->DeleteGlobalRef(device->midiDeviceObj);