Android JNI: Disallow automatic conversion from long to jint

Start using JniIntWrapper from Chromium instead of bypassing
it in jni_generator_helper.h.

Bug: webrtc:8278
Change-Id: I20313e1e610b05f79c210e823ab50cfb2073674e
Reviewed-on: https://webrtc-review.googlesource.com/74841
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23230}
This commit is contained in:
Magnus Jedvert
2018-05-08 10:51:00 +02:00
committed by Commit Bot
parent fdf1f88f62
commit 8a483be137
9 changed files with 75 additions and 27 deletions

View File

@ -1142,12 +1142,8 @@ rtc_static_library("native_api_jni") {
visibility = [ "*" ]
sources = [
"native_api/jni/class_loader.cc",
"native_api/jni/class_loader.h",
"native_api/jni/java_types.cc",
"native_api/jni/java_types.h",
"native_api/jni/jvm.cc",
"native_api/jni/jvm.h",
"native_api/jni/scoped_java_ref.h",
"src/jni/jni_generator_helper.cc",
"src/jni/jni_generator_helper.h",
]
@ -1155,6 +1151,7 @@ rtc_static_library("native_api_jni") {
public = [
"native_api/jni/class_loader.h",
"native_api/jni/java_types.h",
"native_api/jni/jni_int_wrapper.h",
"native_api/jni/jvm.h",
"native_api/jni/scoped_java_ref.h",
]

View File

@ -0,0 +1,59 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Originally this class is from Chromium.
// https://cs.chromium.org/chromium/src/base/android/jni_int_wrapper.h.
#ifndef SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
#define SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
// Wrapper used to receive int when calling Java from native. The wrapper
// disallows automatic conversion of anything besides int32_t to a jint.
// Checking is only done in debugging builds.
#ifdef NDEBUG
typedef jint JniIntWrapper;
// This inline is sufficiently trivial that it does not change the
// final code generated by g++.
inline jint as_jint(JniIntWrapper wrapper) {
return wrapper;
}
#else
class JniIntWrapper {
public:
JniIntWrapper() : i_(0) {}
JniIntWrapper(int32_t i) : i_(i) {} // NOLINT(runtime/explicit)
explicit JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {}
jint as_jint() const { return i_; }
// If you get an "invokes a deleted function" error at the lines below it is
// because you used an implicit conversion to convert e.g. a long to an
// int32_t when calling Java. We disallow this. If you want a lossy
// conversion, please use an explicit conversion in your C++ code.
JniIntWrapper(uint32_t) = delete; // NOLINT(runtime/explicit)
JniIntWrapper(uint64_t) = delete; // NOLINT(runtime/explicit)
JniIntWrapper(int64_t) = delete; // NOLINT(runtime/explicit)
private:
const jint i_;
};
inline jint as_jint(const JniIntWrapper& wrapper) {
return wrapper.as_jint();
}
#endif // NDEBUG
#endif // SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_

View File

@ -522,7 +522,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
// Feed input to decoder.
bool success = Java_MediaCodecVideoDecoder_queueInputBuffer(
jni, j_media_codec_video_decoder_, j_input_buffer_index,
inputImage._length, presentation_timestamp_us,
static_cast<int>(inputImage._length), presentation_timestamp_us,
static_cast<int64_t>(inputImage._timeStamp), inputImage.ntp_time_ms_);
if (CheckException(jni) || !success) {
ALOGE << "queueInputBuffer error";

View File

@ -605,8 +605,8 @@ void GetAudioParameters(JNIEnv* env,
bool use_stereo_output,
AudioParameters* input_parameters,
AudioParameters* output_parameters) {
const size_t output_channels = use_stereo_output ? 2 : 1;
const size_t input_channels = use_stereo_input ? 2 : 1;
const int output_channels = use_stereo_output ? 2 : 1;
const int input_channels = use_stereo_input ? 2 : 1;
const size_t output_buffer_size = Java_WebRtcAudioManager_getOutputBufferSize(
env, j_context, j_audio_manager, sample_rate, output_channels);
const size_t input_buffer_size = Java_WebRtcAudioManager_getInputBufferSize(

View File

@ -107,7 +107,7 @@ int32_t AudioRecordJni::InitRecording() {
int frames_per_buffer = Java_WebRtcAudioRecord_initRecording(
env_, j_audio_record_, audio_parameters_.sample_rate(),
audio_parameters_.channels());
static_cast<int>(audio_parameters_.channels()));
if (frames_per_buffer < 0) {
direct_buffer_address_ = nullptr;
RTC_LOG(LS_ERROR) << "InitRecording failed";

View File

@ -77,9 +77,9 @@ int32_t AudioTrackJni::InitPlayout() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
RTC_DCHECK(!initialized_);
RTC_DCHECK(!playing_);
if (!Java_WebRtcAudioTrack_initPlayout(env_, j_audio_track_,
audio_parameters_.sample_rate(),
audio_parameters_.channels())) {
if (!Java_WebRtcAudioTrack_initPlayout(
env_, j_audio_track_, audio_parameters_.sample_rate(),
static_cast<int>(audio_parameters_.channels()))) {
RTC_LOG(LS_ERROR) << "InitPlayout failed";
return -1;
}
@ -138,7 +138,8 @@ bool AudioTrackJni::SpeakerVolumeIsAvailable() {
int AudioTrackJni::SetSpeakerVolume(uint32_t volume) {
RTC_LOG(INFO) << "SetSpeakerVolume(" << volume << ")";
RTC_DCHECK(thread_checker_.CalledOnValidThread());
return Java_WebRtcAudioTrack_setStreamVolume(env_, j_audio_track_, volume)
return Java_WebRtcAudioTrack_setStreamVolume(env_, j_audio_track_,
static_cast<int>(volume))
? 0
: -1;
}

View File

@ -35,7 +35,8 @@ ScopedJavaLocalRef<jobject> NativeToJavaEncodedImage(
if (image.qp_ != -1)
qp = NativeToJavaInteger(jni, image.qp_);
return Java_EncodedImage_Constructor(
jni, buffer, image._encodedWidth, image._encodedHeight,
jni, buffer, static_cast<int>(image._encodedWidth),
static_cast<int>(image._encodedHeight),
image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec, frame_type,
static_cast<jint>(image.rotation_), image._completeFrame, qp);
}

View File

@ -9,9 +9,7 @@
*/
// Do not include this file directly. It's intended to be used only by the JNI
// generation script. We are exporting types in strange namespaces in order to
// be compatible with the generated code targeted for Chromium. We are bypassing
// the wrapping done by Chromium's JniIntWrapper, JavaRef, and
// ScopedJavaLocalRef, and use raw jobjects instead.
// be compatible with the generated code targeted for Chromium.
#ifndef SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
#define SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
@ -19,6 +17,7 @@
#include <jni.h>
#include "rtc_base/checks.h"
#include "sdk/android/native_api/jni/jni_int_wrapper.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"
#define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
@ -39,15 +38,6 @@ inline void CheckException(JNIEnv* env) {
}
} // namespace jni_generator
namespace { // NOLINT(build/namespaces)
// Bypass JniIntWrapper.
// TODO(magjed): Start using Chromium's JniIntWrapper.
typedef jint JniIntWrapper;
inline jint as_jint(JniIntWrapper wrapper) {
return wrapper;
}
} // namespace
namespace base {
namespace subtle {

View File

@ -75,8 +75,8 @@ int32_t VideoEncoderWrapper::InitEncodeInternal(JNIEnv* jni) {
ScopedJavaLocalRef<jobject> settings = Java_Settings_Constructor(
jni, number_of_cores_, codec_settings_.width, codec_settings_.height,
codec_settings_.startBitrate, codec_settings_.maxFramerate,
automatic_resize_on);
static_cast<int>(codec_settings_.startBitrate),
static_cast<int>(codec_settings_.maxFramerate), automatic_resize_on);
ScopedJavaLocalRef<jobject> callback =
Java_VideoEncoderWrapper_createEncoderCallback(jni,