/* * Init JNI fields that will be used to fetch the key and crypt/encrypt */ static int InitJni(vlc_keystore *p_keystore, JNIEnv *p_env) { jclass clazz = NULL; GET_CLASS("java/lang/Object"); GET_ID(GetMethodID, Object.toString, "toString", "()Ljava/lang/String;"); GET_CLASS("java/security/KeyStore"); GET_GLOBAL_CLASS(KeyStore); GET_ID(GetStaticMethodID, KeyStore.getInstance, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyStore;"); GET_ID(GetMethodID, KeyStore.load, "load", "(Ljava/security/KeyStore$LoadStoreParameter;)V"); GET_ID(GetMethodID, KeyStore.getEntry, "getEntry", "(Ljava/lang/String;Ljava/security/KeyStore$ProtectionParameter;)" "Ljava/security/KeyStore$Entry;"); GET_CLASS("java/security/KeyStore$SecretKeyEntry"); GET_ID(GetMethodID, KeyStore.SecretKeyEntry.getSecretKey, "getSecretKey", "()Ljavax/crypto/SecretKey;"); GET_CLASS("javax/crypto/spec/IvParameterSpec"); GET_GLOBAL_CLASS(IvParameterSpec); GET_ID(GetMethodID, IvParameterSpec.ctor, "<init>", "([B)V"); GET_CLASS("javax/crypto/Cipher"); GET_GLOBAL_CLASS(Cipher); GET_ID(GetStaticMethodID, Cipher.getInstance, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/Cipher;"); GET_ID(GetMethodID, Cipher.init, "init", "(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V"); GET_ID(GetMethodID, Cipher.doFinal, "doFinal", "([B)[B"); GET_ID(GetMethodID, Cipher.getIV, "getIV", "()[B"); GET_CONST_INT(Cipher.ENCRYPT_MODE, "ENCRYPT_MODE"); GET_CONST_INT(Cipher.DECRYPT_MODE, "DECRYPT_MODE"); DEL_LREF(clazz); jstring VLC_CIPHER = NEW_STR("AES/CBC/PKCS7Padding"); if (CHECK_EXCEPTION()) return VLC_EGENERIC; fields.VLC_CIPHER = NEW_GREF(VLC_CIPHER); DEL_LREF(VLC_CIPHER); return VLC_SUCCESS; }
/* * Init JNI fields that will be used by generateKey() */ static int InitJniGenKey(vlc_keystore *p_keystore, JNIEnv *p_env) { jclass clazz = NULL; GET_CLASS("android/security/keystore/KeyProperties"); GET_CONST_INT(KeyProperties.PURPOSE_ENCRYPT, "PURPOSE_ENCRYPT"); GET_CONST_INT(KeyProperties.PURPOSE_DECRYPT, "PURPOSE_DECRYPT"); GET_CONST_OBJ(KeyProperties.BLOCK_MODE_CBC, "BLOCK_MODE_CBC", "Ljava/lang/String;"); GET_CONST_OBJ(KeyProperties.ENCRYPTION_PADDING_PKCS7, "ENCRYPTION_PADDING_PKCS7", "Ljava/lang/String;"); GET_CONST_OBJ(KeyProperties.KEY_ALGORITHM_AES, "KEY_ALGORITHM_AES", "Ljava/lang/String;"); GET_CLASS("android/security/keystore/KeyGenParameterSpec$Builder"); GET_GLOBAL_CLASS(KeyGenParameterSpec.Builder); GET_ID(GetMethodID, KeyGenParameterSpec.Builder.ctor, "<init>", "(Ljava/lang/String;I)V"); GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setKeySize, "setKeySize", "(I)Landroid/security/keystore/KeyGenParameterSpec$Builder;"); GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setBlockModes, "setBlockModes", "([Ljava/lang/String;)" "Landroid/security/keystore/KeyGenParameterSpec$Builder;"); GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setEncryptionPaddings, "setEncryptionPaddings", "([Ljava/lang/String;)" "Landroid/security/keystore/KeyGenParameterSpec$Builder;"); GET_ID(GetMethodID, KeyGenParameterSpec.Builder.build, "build", "()Landroid/security/keystore/KeyGenParameterSpec;"); GET_CLASS("javax/crypto/KeyGenerator"); GET_GLOBAL_CLASS(KeyGenerator); GET_ID(GetStaticMethodID, KeyGenerator.getInstance, "getInstance", "(Ljava/lang/String;Ljava/lang/String;)Ljavax/crypto/KeyGenerator;"); GET_ID(GetMethodID, KeyGenerator.init, "init", "(Ljava/security/spec/AlgorithmParameterSpec;)V"); GET_ID(GetMethodID, KeyGenerator.generateKey, "generateKey", "()Ljavax/crypto/SecretKey;"); DEL_LREF(clazz); return VLC_SUCCESS; }
/* init all jni fields. * Done only one time during the first initialisation */ static bool InitJNIFields( audio_output_t *p_aout ) { static vlc_mutex_t lock = VLC_STATIC_MUTEX; static int i_init_state = -1; bool ret; jclass clazz; jfieldID field; JNIEnv* env = NULL; vlc_mutex_lock( &lock ); if( i_init_state != -1 ) goto end; if (!(env = jni_get_env(THREAD_NAME))) { i_init_state = 0; goto end; } #define CHECK_EXCEPTION( what, critical ) do { \ if( (*env)->ExceptionOccurred( env ) ) \ { \ msg_Err( p_aout, "%s failed", what ); \ (*env)->ExceptionClear( env ); \ if( (critical) ) \ { \ i_init_state = 0; \ goto end; \ } \ } \ } while( 0 ) #define GET_CLASS( str, critical ) do { \ clazz = (*env)->FindClass( env, (str) ); \ CHECK_EXCEPTION( str, critical ); \ } while( 0 ) #define GET_ID( get, id, str, args, critical ) do { \ jfields.id = (*env)->get( env, clazz, (str), (args) ); \ CHECK_EXCEPTION( #get, critical ); \ } while( 0 ) #define GET_CONST_INT( id, str, critical ) do { \ field = NULL; \ field = (*env)->GetStaticFieldID( env, clazz, (str), "I" ); \ CHECK_EXCEPTION( #id, critical ); \ if( field ) \ { \ jfields.id = (*env)->GetStaticIntField( env, clazz, field ); \ CHECK_EXCEPTION( #id, critical ); \ } \ } while( 0 ) /* AudioTrack class init */ GET_CLASS( "android/media/AudioTrack", true ); jfields.AudioTrack.clazz = (jclass) (*env)->NewGlobalRef( env, clazz ); CHECK_EXCEPTION( "NewGlobalRef", true ); GET_ID( GetMethodID, AudioTrack.ctor, "<init>", "(IIIIII)V", true ); GET_ID( GetMethodID, AudioTrack.release, "release", "()V", true ); GET_ID( GetMethodID, AudioTrack.getState, "getState", "()I", true ); GET_ID( GetMethodID, AudioTrack.play, "play", "()V", true ); GET_ID( GetMethodID, AudioTrack.stop, "stop", "()V", true ); GET_ID( GetMethodID, AudioTrack.flush, "flush", "()V", true ); GET_ID( GetMethodID, AudioTrack.pause, "pause", "()V", true ); GET_ID( GetMethodID, AudioTrack.writeV21, "write", "(Ljava/nio/ByteBuffer;II)I", false ); if( jfields.AudioTrack.writeV21 ) { GET_CONST_INT( AudioTrack.WRITE_NON_BLOCKING, "WRITE_NON_BLOCKING", true ); #ifdef AUDIOTRACK_USE_FLOAT GET_ID( GetMethodID, AudioTrack.writeFloat, "write", "([FIII)I", true ); #endif } else GET_ID( GetMethodID, AudioTrack.write, "write", "([BII)I", true ); #ifdef AUDIOTRACK_HW_LATENCY GET_ID( GetMethodID, AudioTrack.getTimestamp, "getTimestamp", "(Landroid/media/AudioTimestamp;)Z", false ); #endif GET_ID( GetMethodID, AudioTrack.getPlaybackHeadPosition, "getPlaybackHeadPosition", "()I", true ); GET_ID( GetStaticMethodID, AudioTrack.getMinBufferSize, "getMinBufferSize", "(III)I", true ); #ifdef AUDIOTRACK_NATIVE_SAMPLERATE GET_ID( GetStaticMethodID, AudioTrack.getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I", true ); #endif GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true ); GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true ); GET_CONST_INT( AudioTrack.ERROR, "ERROR", true ); GET_CONST_INT( AudioTrack.ERROR_BAD_VALUE , "ERROR_BAD_VALUE", true ); GET_CONST_INT( AudioTrack.ERROR_INVALID_OPERATION, "ERROR_INVALID_OPERATION", true ); /* AudioTimestamp class init (if any) */ if( jfields.AudioTrack.getTimestamp ) { GET_CLASS( "android/media/AudioTimestamp", true ); jfields.AudioTimestamp.clazz = (jclass) (*env)->NewGlobalRef( env, clazz ); CHECK_EXCEPTION( "NewGlobalRef", true ); GET_ID( GetMethodID, AudioTimestamp.ctor, "<init>", "()V", true ); GET_ID( GetFieldID, AudioTimestamp.framePosition, "framePosition", "J", true ); GET_ID( GetFieldID, AudioTimestamp.nanoTime, "nanoTime", "J", true ); } #ifdef AUDIOTRACK_HW_LATENCY /* AudioSystem class init */ GET_CLASS( "android/media/AudioSystem", false ); if( clazz ) { jfields.AudioSystem.clazz = (jclass) (*env)->NewGlobalRef( env, clazz ); GET_ID( GetStaticMethodID, AudioSystem.getOutputLatency, "getOutputLatency", "(I)I", false ); } #endif /* AudioFormat class init */ GET_CLASS( "android/media/AudioFormat", true ); GET_CONST_INT( AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT", true ); GET_CONST_INT( AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT", true ); #ifdef AUDIOTRACK_USE_FLOAT GET_CONST_INT( AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT", false ); jfields.AudioFormat.has_ENCODING_PCM_FLOAT = field != NULL && jfields.AudioTrack.writeFloat; #else jfields.AudioFormat.has_ENCODING_PCM_FLOAT = false; #endif GET_CONST_INT( AudioFormat.ENCODING_AC3, "ENCODING_AC3", false ); if( field != NULL ) { GET_CONST_INT( AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3", false ); jfields.AudioFormat.has_ENCODING_AC3 = field != NULL; } else jfields.AudioFormat.has_ENCODING_AC3 = false; GET_CONST_INT( AudioFormat.CHANNEL_OUT_MONO, "CHANNEL_OUT_MONO", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_LEFT, "CHANNEL_OUT_FRONT_LEFT", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER", true ); GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT", false ); if( field != NULL ) { GET_CONST_INT( AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT", true ); jfields.AudioFormat.has_CHANNEL_OUT_SIDE = true; } else jfields.AudioFormat.has_CHANNEL_OUT_SIDE = false; /* AudioManager class init */ GET_CLASS( "android/media/AudioManager", true ); GET_CONST_INT( AudioManager.ERROR_DEAD_OBJECT, "ERROR_DEAD_OBJECT", false ); jfields.AudioManager.has_ERROR_DEAD_OBJECT = field != NULL; GET_CONST_INT( AudioManager.STREAM_MUSIC, "STREAM_MUSIC", true ); #undef CHECK_EXCEPTION #undef GET_CLASS #undef GET_ID #undef GET_CONST_INT i_init_state = 1; end: ret = i_init_state == 1; if( !ret ) msg_Err( p_aout, "AudioTrack jni init failed" ); vlc_mutex_unlock( &lock ); return ret; }