Reland of Removes usage of native base::android::GetApplicationContext()

The change is now compatible with the old JVM::Initialize API. The
context is passed to the ContextUtils class when calling its deprecated
signature.

BUG=webrtc:7665
NOTRY=True # Only comment changes since the last patchset.

Review-Url: https://codereview.webrtc.org/2903253004
Cr-Commit-Position: refs/heads/master@{#18268}
This commit is contained in:
sakal
2017-05-26 01:51:53 -07:00
committed by Commit bot
parent 13ae11a418
commit d7fdb8014d
18 changed files with 196 additions and 54 deletions

View File

@ -11,12 +11,14 @@
package org.webrtc;
import android.content.Context;
import org.webrtc.Logging;
/**
* Class for storing the application context and retrieving it in a static context. Similar to
* org.chromium.base.ContextUtils.
*/
public class ContextUtils {
private static final String TAG = "ContextUtils";
private static Context applicationContext;
/**
@ -25,7 +27,10 @@ public class ContextUtils {
*/
public static void initialize(Context applicationContext) {
if (ContextUtils.applicationContext != null) {
throw new RuntimeException("Multiple ContextUtils.initialize calls.");
// TODO(sakal): Re-enable after the migration period.
// throw new RuntimeException("Multiple ContextUtils.initialize calls.");
Logging.e(
TAG, "Calling ContextUtils.initialize multiple times, this will crash in the future!");
}
if (applicationContext == null) {
throw new RuntimeException("Application context cannot be null for ContextUtils.initialize.");

View File

@ -83,11 +83,10 @@ AudioManager::AudioManager()
j_native_registration_ = j_environment_->RegisterNatives(
"org/webrtc/voiceengine/WebRtcAudioManager", native_methods,
arraysize(native_methods));
j_audio_manager_.reset(new JavaAudioManager(
j_native_registration_.get(),
j_audio_manager_.reset(
new JavaAudioManager(j_native_registration_.get(),
j_native_registration_->NewObject(
"<init>", "(Landroid/content/Context;J)V",
JVM::GetInstance()->context(), PointerTojlong(this))));
"<init>", "(J)V", PointerTojlong(this))));
}
AudioManager::~AudioManager() {

View File

@ -90,11 +90,10 @@ AudioRecordJni::AudioRecordJni(AudioManager* audio_manager)
j_native_registration_ = j_environment_->RegisterNatives(
"org/webrtc/voiceengine/WebRtcAudioRecord", native_methods,
arraysize(native_methods));
j_audio_record_.reset(new JavaAudioRecord(
j_native_registration_.get(),
j_audio_record_.reset(
new JavaAudioRecord(j_native_registration_.get(),
j_native_registration_->NewObject(
"<init>", "(Landroid/content/Context;J)V",
JVM::GetInstance()->context(), PointerTojlong(this))));
"<init>", "(J)V", PointerTojlong(this))));
// Detach from this thread since we want to use the checker to verify calls
// from the Java based audio thread.
thread_checker_java_.DetachFromThread();

View File

@ -89,11 +89,10 @@ AudioTrackJni::AudioTrackJni(AudioManager* audio_manager)
j_native_registration_ = j_environment_->RegisterNatives(
"org/webrtc/voiceengine/WebRtcAudioTrack", native_methods,
arraysize(native_methods));
j_audio_track_.reset(new JavaAudioTrack(
j_native_registration_.get(),
j_audio_track_.reset(
new JavaAudioTrack(j_native_registration_.get(),
j_native_registration_->NewObject(
"<init>", "(Landroid/content/Context;J)V",
JVM::GetInstance()->context(), PointerTojlong(this))));
"<init>", "(J)V", PointerTojlong(this))));
// Detach from this thread since we want to use the checker to verify calls
// from the Java based audio thread.
thread_checker_java_.DetachFromThread();

View File

@ -17,7 +17,6 @@
// Note: this dependency is dangerous since it reaches into Chromium's base.
// There's a risk of e.g. macro clashes. This file may only be used in tests.
RTC_PUSH_IGNORING_WUNDEF()
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
RTC_POP_IGNORING_WUNDEF()
#include "webrtc/base/checks.h"
@ -35,10 +34,9 @@ void EnsureInitializedOnce() {
JNIEnv* jni = ::base::android::AttachCurrentThread();
JavaVM* jvm = NULL;
RTC_CHECK_EQ(0, jni->GetJavaVM(&jvm));
jobject context = ::base::android::GetApplicationContext().obj();
// Initialize the Java environment (currently only used by the audio manager).
webrtc::JVM::Initialize(jvm, context);
webrtc::JVM::Initialize(jvm);
}
void EnsureInitialized() {

View File

@ -20,6 +20,7 @@ import android.media.AudioTrack;
import android.os.Build;
import java.util.Timer;
import java.util.TimerTask;
import org.webrtc.ContextUtils;
import org.webrtc.Logging;
// WebRtcAudioManager handles tasks that uses android.media.AudioManager.
@ -135,7 +136,6 @@ public class WebRtcAudioManager {
}
private final long nativeAudioManager;
private final Context context;
private final AudioManager audioManager;
private boolean initialized = false;
@ -156,11 +156,11 @@ public class WebRtcAudioManager {
private final VolumeLogger volumeLogger;
WebRtcAudioManager(Context context, long nativeAudioManager) {
WebRtcAudioManager(long nativeAudioManager) {
Logging.d(TAG, "ctor" + WebRtcAudioUtils.getThreadInfo());
this.context = context;
this.nativeAudioManager = nativeAudioManager;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager =
(AudioManager) ContextUtils.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
if (DEBUG) {
WebRtcAudioUtils.logDeviceInfo(TAG);
}
@ -224,12 +224,14 @@ public class WebRtcAudioManager {
// Gets the current earpiece state.
private boolean hasEarpiece() {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
return ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
}
// Returns true if low-latency audio output is supported.
private boolean isLowLatencyOutputSupported() {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
return ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUDIO_LOW_LATENCY);
}
// Returns true if low-latency audio input is supported.
@ -248,7 +250,8 @@ public class WebRtcAudioManager {
@TargetApi(23)
private boolean isProAudioSupported() {
return WebRtcAudioUtils.runningOnMarshmallowOrHigher()
&& context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
&& ContextUtils.getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUDIO_PRO);
}
// Returns the native output sample rate for this device's output stream.

View File

@ -19,6 +19,7 @@ import android.os.Process;
import java.lang.System;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import org.webrtc.ContextUtils;
import org.webrtc.Logging;
import org.webrtc.ThreadUtils;
@ -47,7 +48,6 @@ public class WebRtcAudioRecord {
private static final long AUDIO_RECORD_THREAD_JOIN_TIMEOUT_MS = 2000;
private final long nativeAudioRecord;
private final Context context;
private WebRtcAudioEffects effects = null;
@ -139,9 +139,8 @@ public class WebRtcAudioRecord {
}
}
WebRtcAudioRecord(Context context, long nativeAudioRecord) {
WebRtcAudioRecord(long nativeAudioRecord) {
Logging.d(TAG, "ctor" + WebRtcAudioUtils.getThreadInfo());
this.context = context;
this.nativeAudioRecord = nativeAudioRecord;
if (DEBUG) {
WebRtcAudioUtils.logDeviceInfo(TAG);
@ -169,7 +168,8 @@ public class WebRtcAudioRecord {
private int initRecording(int sampleRate, int channels) {
Logging.d(TAG, "initRecording(sampleRate=" + sampleRate + ", channels=" + channels + ")");
if (!WebRtcAudioUtils.hasPermission(context, android.Manifest.permission.RECORD_AUDIO)) {
if (!WebRtcAudioUtils.hasPermission(
ContextUtils.getApplicationContext(), android.Manifest.permission.RECORD_AUDIO)) {
reportWebRtcAudioRecordInitError("RECORD_AUDIO permission is missing");
return -1;
}

View File

@ -19,6 +19,7 @@ import android.media.AudioTrack;
import android.os.Process;
import java.lang.Thread;
import java.nio.ByteBuffer;
import org.webrtc.ContextUtils;
import org.webrtc.Logging;
public class WebRtcAudioTrack {
@ -36,7 +37,6 @@ public class WebRtcAudioTrack {
// Average number of callbacks per second.
private static final int BUFFERS_PER_SECOND = 1000 / CALLBACK_BUFFER_SIZE_MS;
private final Context context;
private final long nativeAudioTrack;
private final AudioManager audioManager;
@ -165,11 +165,11 @@ public class WebRtcAudioTrack {
}
}
WebRtcAudioTrack(Context context, long nativeAudioTrack) {
WebRtcAudioTrack(long nativeAudioTrack) {
Logging.d(TAG, "ctor" + WebRtcAudioUtils.getThreadInfo());
this.context = context;
this.nativeAudioTrack = nativeAudioTrack;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager =
(AudioManager) ContextUtils.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
if (DEBUG) {
WebRtcAudioUtils.logDeviceInfo(TAG);
}

View File

@ -118,8 +118,7 @@ class JNIEnvironment {
// JNIEnv* jni = ::base::android::AttachCurrentThread();
// JavaVM* jvm = NULL;
// jni->GetJavaVM(&jvm);
// jobject context = ::base::android::GetApplicationContext();
// webrtc::JVM::Initialize(jvm, context);
// webrtc::JVM::Initialize(jvm);
//
// // Header (.h) file of example class called User.
// std::unique_ptr<JNIEnvironment> env;
@ -145,8 +144,13 @@ class JNIEnvironment {
// JVM::Uninitialize();
class JVM {
public:
// Stores global handles to the Java VM interface and the application context.
// Stores global handles to the Java VM interface.
// Should be called once on a thread that is attached to the JVM.
static void Initialize(JavaVM* jvm);
// TODO(sakal): Remove once downstream dependencies have been updated.
// DEPRECATED (crbug.com/webrtc/7710): Old signature taking the Android
// context as a parameter. Currently passes in the context to the ContextUtils
// class.
static void Initialize(JavaVM* jvm, jobject context);
// Clears handles stored in Initialize(). Must be called on same thread as
// Initialize().
@ -168,10 +172,9 @@ class JVM {
// TODO(henrika): can we make these private?
JavaVM* jvm() const { return jvm_; }
jobject context() const { return context_; }
protected:
JVM(JavaVM* jvm, jobject context);
JVM(JavaVM* jvm);
~JVM();
private:
@ -179,7 +182,6 @@ class JVM {
rtc::ThreadChecker thread_checker_;
JavaVM* const jvm_;
jobject context_;
};
} // namespace webrtc

View File

@ -217,10 +217,21 @@ std::string JNIEnvironment::JavaToStdString(const jstring& j_string) {
}
// static
void JVM::Initialize(JavaVM* jvm, jobject context) {
void JVM::Initialize(JavaVM* jvm) {
ALOGD("JVM::Initialize%s", GetThreadInfo().c_str());
RTC_CHECK(!g_jvm);
g_jvm = new JVM(jvm, context);
g_jvm = new JVM(jvm);
}
void JVM::Initialize(JavaVM* jvm, jobject context) {
Initialize(jvm);
// Pass in the context to the new ContextUtils class.
JNIEnv* jni = g_jvm->jni();
jclass context_utils = FindClass(jni, "org/webrtc/ContextUtils");
jmethodID initialize_method = jni->GetStaticMethodID(
context_utils, "initialize", "(Landroid/content/Context;)V");
jni->CallStaticVoidMethod(context_utils, initialize_method, context);
}
// static
@ -237,11 +248,9 @@ JVM* JVM::GetInstance() {
return g_jvm;
}
JVM::JVM(JavaVM* jvm, jobject context)
: jvm_(jvm) {
JVM::JVM(JavaVM* jvm) : jvm_(jvm) {
ALOGD("JVM::JVM%s", GetThreadInfo().c_str());
RTC_CHECK(jni()) << "AttachCurrentThread() must be called on this thread.";
context_ = NewGlobalRef(jni(), context);
LoadClasses(jni());
}
@ -249,7 +258,6 @@ JVM::~JVM() {
ALOGD("JVM::~JVM%s", GetThreadInfo().c_str());
RTC_DCHECK(thread_checker_.CalledOnValidThread());
FreeClassReferences(jni());
DeleteGlobalRef(jni(), context_);
}
std::unique_ptr<JNIEnvironment> JVM::environment() {

View File

@ -19,7 +19,6 @@
// Since we use Chromes build system for creating the gtest binary, this should
// be fine.
RTC_PUSH_IGNORING_WUNDEF()
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
RTC_POP_IGNORING_WUNDEF()
@ -41,11 +40,10 @@ void EnsureInitializedOnce() {
JNIEnv* jni = ::base::android::AttachCurrentThread();
JavaVM* jvm = NULL;
RTC_CHECK_EQ(0, jni->GetJavaVM(&jvm));
jobject context = ::base::android::GetApplicationContext().obj();
RTC_CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
webrtc::JVM::Initialize(jvm, context);
webrtc::JVM::Initialize(jvm);
}
} // anonymous namespace

View File

@ -10,6 +10,7 @@
package org.webrtc;
import android.content.Context;
import java.util.List;
/**
@ -30,6 +31,7 @@ public class PeerConnectionFactory {
private static final String TAG = "PeerConnectionFactory";
private final long nativeFactory;
private static Context applicationContext;
private static Thread networkThread;
private static Thread workerThread;
private static Thread signalingThread;
@ -52,14 +54,19 @@ public class PeerConnectionFactory {
// Must be called at least once before creating a PeerConnectionFactory
// (for example, at application startup time).
public static native void initializeAndroidGlobals(
android.content.Context context, boolean videoHwAcceleration);
public static native void nativeInitializeAndroidGlobals(
Context context, boolean videoHwAcceleration);
public static void initializeAndroidGlobals(Context context, boolean videoHwAcceleration) {
ContextUtils.initialize(context);
nativeInitializeAndroidGlobals(context, videoHwAcceleration);
}
// Older signature of initializeAndroidGlobals. The extra parameters are now meaningless.
@Deprecated
public static boolean initializeAndroidGlobals(Object context, boolean initializeAudio,
boolean initializeVideo, boolean videoHwAcceleration) {
initializeAndroidGlobals((android.content.Context) context, videoHwAcceleration);
initializeAndroidGlobals((Context) context, videoHwAcceleration);
return true;
}

View File

@ -1139,7 +1139,7 @@ JOW(jlong, PeerConnectionFactory_nativeCreateObserver)(
return (jlong)new PCOJava(jni, j_observer);
}
JOW(void, PeerConnectionFactory_initializeAndroidGlobals)
JOW(void, PeerConnectionFactory_nativeInitializeAndroidGlobals)
(JNIEnv* jni,
jclass,
jobject context,
@ -1149,7 +1149,7 @@ JOW(void, PeerConnectionFactory_initializeAndroidGlobals)
if (!factory_static_initialized) {
RTC_DCHECK(j_application_context == nullptr);
j_application_context = NewGlobalRef(jni, context);
webrtc::JVM::Initialize(GetJVM(), context);
webrtc::JVM::Initialize(GetJVM());
factory_static_initialized = true;
}
}

View File

@ -532,3 +532,17 @@ rtc_source_set("audio_codec_mocks") {
"//testing/gmock",
]
}
if (!build_with_chromium && is_android) {
android_library("native_test_java") {
testonly = true
java_files = [
"android/org/webrtc/native_test/RTCNativeUnitTest.java",
"android/org/webrtc/native_test/RTCNativeUnitTestActivity.java",
]
deps = [
"//testing/android/native_test:native_test_java",
"//webrtc/base:base_java",
]
}
}

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.webrtc.native_test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:label="NativeTests"
android:name="org.chromium.base.BaseChromiumApplication">
<uses-library android:name="android.test.runner"/>
<activity android:name=".RTCNativeUnitTestActivity"
android:label="NativeTest"
android:configChanges="orientation|keyboardHidden"
android:process=":test_process">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner"
android:targetPackage="org.webrtc.native_test"
android:label="Instrumentation entry point for org.webrtc.native_test"/>
</manifest>

View File

@ -0,0 +1,26 @@
/*
* Copyright 2017 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.
*/
package org.webrtc.native_test;
import android.app.Activity;
import org.chromium.native_test.NativeUnitTest;
import org.webrtc.ContextUtils;
/**
* Native unit test that calls ContextUtils.initialize for WebRTC.
*/
public class RTCNativeUnitTest extends NativeUnitTest {
@Override
public void preCreate(Activity activity) {
super.preCreate(activity);
ContextUtils.initialize(activity.getApplicationContext());
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2017 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.
*/
package org.webrtc.native_test;
import android.app.Activity;
import android.os.Bundle;
/**
* Activity that uses RTCNativeUnitTest to run the tests.
*/
public class RTCNativeUnitTestActivity extends Activity {
private RTCNativeUnitTest mTest = new RTCNativeUnitTest();
@Override
public void onCreate(Bundle savedInstanceState) {
mTest.preCreate(this);
super.onCreate(savedInstanceState);
mTest.postCreate(this);
}
@Override
public void onStart() {
super.onStart();
mTest.postStart(this, false);
}
}

View File

@ -266,6 +266,10 @@ template("rtc_test") {
if (defined(invoker.public_configs)) {
public_configs += invoker.public_configs
}
if (!build_with_chromium && is_android) {
android_manifest = "//webrtc/test/android/AndroidManifest.xml"
deps += [ "//webrtc/test:native_test_java" ]
}
}
}