Loading services/core/jni/BroadcastRadio/BroadcastRadioService.cpp +13 −10 Original line number Diff line number Diff line Loading @@ -27,14 +27,17 @@ #include <android/hidl/manager/1.0/IServiceManager.h> #include <core_jni_helpers.h> #include <hidl/ServiceManagement.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> #include <JNIHelp.h> namespace android { namespace server { namespace BroadcastRadio { namespace BroadcastRadioService { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_string; using hardware::hidl_vec; Loading @@ -50,7 +53,7 @@ using V1_0::ProgramInfo; using V1_0::MetaData; using V1_0::ITuner; static Mutex gContextMutex; static mutex gContextMutex; static struct { struct { Loading Loading @@ -90,8 +93,8 @@ static ServiceContext& getNativeContext(jlong nativeContextHandle) { } static jlong nativeInit(JNIEnv *env, jobject obj) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto nativeContext = new ServiceContext(); static_assert(sizeof(jlong) >= sizeof(nativeContext), "jlong is smaller than a pointer"); Loading @@ -99,16 +102,16 @@ static jlong nativeInit(JNIEnv *env, jobject obj) { } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<ServiceContext*>(nativeContext); delete ctx; } static jobject nativeLoadModules(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeLoadModules()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); // Get list of registered HIDL HAL implementations. Loading Loading @@ -182,8 +185,8 @@ static jobject nativeLoadModules(JNIEnv *env, jobject obj, jlong nativeContext) static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jint moduleId, jobject bandConfig, bool withAudio, jobject callback) { ALOGV("nativeOpenTuner()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (callback == nullptr) { Loading services/core/jni/BroadcastRadio/NativeCallbackThread.cpp +25 −33 Original line number Diff line number Diff line Loading @@ -23,45 +23,38 @@ namespace android { NativeCallbackThread::NativeCallbackThread(JavaVM *vm) : mExitting(false), mvm(vm) { auto res = pthread_create(&mThread, nullptr, main, this); if (res != 0) { ALOGE("Couldn't start NativeCallbackThread"); mThread = 0; return; } using std::lock_guard; using std::mutex; using std::unique_lock; NativeCallbackThread::NativeCallbackThread(JavaVM *vm) : mvm(vm), mExiting(false), mThread(&NativeCallbackThread::threadLoop, this) { ALOGD("Started native callback thread %p", this); } NativeCallbackThread::~NativeCallbackThread() { ALOGV("~NativeCallbackThread %p", this); ALOGV("%s %p", __func__, this); stop(); } void* NativeCallbackThread::main(void *args) { auto self = reinterpret_cast<NativeCallbackThread*>(args); self->main(); return nullptr; } void NativeCallbackThread::main() { ALOGV("NativeCallbackThread::main()"); void NativeCallbackThread::threadLoop() { ALOGV("%s", __func__); JNIEnv *env = nullptr; JavaVMAttachArgs aargs = {JNI_VERSION_1_4, "NativeCallbackThread", nullptr}; if (mvm->AttachCurrentThread(&env, &aargs) != JNI_OK || env == nullptr) { ALOGE("Couldn't attach thread"); mExiting = true; return; } while (!mExitting) { while (!mExiting) { ALOGV("Waiting for task..."); Task task; { AutoMutex _l(mQueueMutex); auto res = mQueueCond.wait(mQueueMutex); ALOGE_IF(res != 0, "Wait failed: %d", res); if (mExitting || res != 0) break; unique_lock<mutex> lk(mQueueMutex); mQueueCond.wait(lk); if (mExiting) break; if (mQueue.empty()) continue; task = mQueue.front(); Loading @@ -84,36 +77,35 @@ void NativeCallbackThread::main() { } void NativeCallbackThread::enqueue(const Task &task) { AutoMutex _l(mQueueMutex); lock_guard<mutex> lk(mQueueMutex); if (mThread == 0 || mExitting) { if (mExiting) { ALOGW("Callback thread %p is not serving calls", this); return; } mQueue.push(task); mQueueCond.signal(); mQueueCond.notify_one(); } void NativeCallbackThread::stop() { ALOGV("stop() %p", this); ALOGV("%s %p", __func__, this); { AutoMutex _l(mQueueMutex); lock_guard<mutex> lk(mQueueMutex); if (mThread == 0 || mExitting) return; if (mExiting) return; mExitting = true; mQueueCond.signal(); mExiting = true; mQueueCond.notify_one(); } if (pthread_self() == mThread) { if (mThread.get_id() == std::thread::id()) { // you can't self-join a thread, but it's ok when calling from our sub-task ALOGD("About to stop native callback thread %p", this); mThread.detach(); } else { auto ret = pthread_join(mThread, nullptr); ALOGE_IF(ret != 0, "Couldn't join thread: %d", ret); mThread.join(); ALOGD("Stopped native callback thread %p", this); } } Loading services/core/jni/BroadcastRadio/NativeCallbackThread.h +7 −10 Original line number Diff line number Diff line Loading @@ -20,26 +20,23 @@ #include <android-base/macros.h> #include <functional> #include <jni.h> #include <pthread.h> #include <queue> #include <utils/Condition.h> #include <utils/Mutex.h> #include <thread> namespace android { class NativeCallbackThread { typedef std::function<void(JNIEnv*)> Task; pthread_t mThread; Mutex mQueueMutex; Condition mQueueCond; std::atomic<bool> mExitting; JavaVM *mvm; std::queue<Task> mQueue; static void* main(void *args); void main(); std::mutex mQueueMutex; std::condition_variable mQueueCond; std::atomic<bool> mExiting; std::thread mThread; void threadLoop(); DISALLOW_COPY_AND_ASSIGN(NativeCallbackThread); Loading services/core/jni/BroadcastRadio/Tuner.cpp +35 −29 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ #include "convert.h" #include "TunerCallback.h" #include <JNIHelp.h> #include <Utils.h> #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h> #include <binder/IPCThreadState.h> #include <broadcastradio-utils/Utils.h> #include <core_jni_helpers.h> #include <media/AudioSystem.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> namespace android { Loading @@ -35,6 +35,9 @@ namespace server { namespace BroadcastRadio { namespace Tuner { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_death_recipient; using hardware::hidl_vec; Loading @@ -49,7 +52,7 @@ using V1_0::Result; using V1_1::ITunerCallback; using V1_1::ProgramListResult; static Mutex gContextMutex; static mutex gContextMutex; static struct { struct { Loading Loading @@ -106,8 +109,8 @@ static TunerContext& getNativeContext(JNIEnv *env, JavaRef<jobject> const &jTune } static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev, bool withAudio, jint band) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = new TunerContext(); ctx->mHalRev = static_cast<HalRevision>(halRev); Loading @@ -119,8 +122,8 @@ static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev, bool withAudio, j } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<TunerContext*>(nativeContext); delete ctx; Loading Loading @@ -150,10 +153,9 @@ static void notifyAudioService(TunerContext& ctx, bool connected) { void assignHalInterfaces(JNIEnv *env, JavaRef<jobject> const &jTuner, sp<V1_0::IBroadcastRadio> halModule, sp<V1_0::ITuner> halTuner) { ALOGV("setHalTuner(%p)", halTuner.get()); ALOGV("%s(%p)", __func__, halTuner.get()); ALOGE_IF(halTuner == nullptr, "HAL tuner is a nullptr"); AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(env, jTuner); if (ctx.mIsClosed) { Loading Loading @@ -187,12 +189,12 @@ static sp<V1_0::ITuner> getHalTuner(const TunerContext& ctx) { } sp<V1_0::ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); return getHalTuner(getNativeContext(nativeContext)); } sp<V1_1::ITuner> getHalTuner11(jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); return getNativeContext(nativeContext).mHalTuner11; } Loading @@ -206,8 +208,9 @@ Region getRegion(JNIEnv *env, jobject obj) { } static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mIsClosed) return; ctx.mIsClosed = true; Loading @@ -228,9 +231,10 @@ static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner = getHalTuner(ctx); if (halTuner == nullptr) return; Loading @@ -244,7 +248,7 @@ static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, Region region) { ALOGV("nativeSetConfiguration()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return nullptr; Loading @@ -263,7 +267,7 @@ static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeCont static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeStep()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -273,7 +277,7 @@ static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeScan()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -282,9 +286,10 @@ static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, } static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jobject jSelector) { ALOGV("nativeTune()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner10 = getHalTuner(ctx); auto halTuner11 = ctx.mHalTuner11; if (halTuner10 == nullptr) return; Loading @@ -304,7 +309,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jobject jS } static void nativeCancel(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeCancel()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -323,9 +328,10 @@ static void nativeCancelAnnouncement(JNIEnv *env, jobject obj, jlong nativeConte } static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeGetProgramInformation()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner10 = getHalTuner(ctx); auto halTuner11 = ctx.mHalTuner11; if (halTuner10 == nullptr) return nullptr; Loading Loading @@ -355,7 +361,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ } static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeStartBackgroundScan()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { ALOGI("Background scan is not supported with HAL < 1.1"); Loading @@ -369,7 +375,7 @@ static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeCont } static jobject nativeGetProgramList(JNIEnv *env, jobject obj, jlong nativeContext, jstring jFilter) { ALOGV("nativeGetProgramList()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { ALOGI("Program list is not supported with HAL < 1.1"); Loading Loading @@ -398,7 +404,7 @@ static jobject nativeGetProgramList(JNIEnv *env, jobject obj, jlong nativeContex static jbyteArray nativeGetImage(JNIEnv *env, jobject obj, jlong nativeContext, jint id) { ALOGV("%s(%x)", __func__, id); AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mHalModule11 == nullptr) { Loading Loading @@ -435,7 +441,7 @@ static jbyteArray nativeGetImage(JNIEnv *env, jobject obj, jlong nativeContext, } static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeIsAnalogForced()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", Loading @@ -456,7 +462,7 @@ static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) } static void nativeSetAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext, bool isForced) { ALOGV("nativeSetAnalogForced()"); ALOGV("%s(%d)", __func__, isForced); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", Loading @@ -469,7 +475,7 @@ static void nativeSetAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext, } static bool nativeIsAntennaConnected(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeIsAntennaConnected()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return false; Loading services/core/jni/BroadcastRadio/TunerCallback.cpp +28 −25 Original line number Diff line number Diff line Loading @@ -22,9 +22,9 @@ #include "Tuner.h" #include "convert.h" #include <JNIHelp.h> #include <Utils.h> #include <broadcastradio-utils/Utils.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> namespace android { Loading @@ -32,6 +32,9 @@ namespace server { namespace BroadcastRadio { namespace TunerCallback { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_vec; Loading Loading @@ -76,7 +79,7 @@ enum class TunerError : jint { BACKGROUND_SCAN_FAILED = 6, }; static Mutex gContextMutex; static mutex gContextMutex; class NativeCallback : public ITunerCallback { jobject mJTuner; Loading Loading @@ -122,13 +125,13 @@ private: NativeCallback::NativeCallback(JNIEnv *env, jobject jTuner, jobject jCallback, HalRevision halRev) : mCallbackThread(gvm), mHalRev(halRev) { ALOGV("NativeCallback()"); ALOGV("%s", __func__); mJTuner = env->NewGlobalRef(jTuner); mJCallback = env->NewGlobalRef(jCallback); } NativeCallback::~NativeCallback() { ALOGV("~NativeCallback()"); ALOGV("%s", __func__); // stop callback thread before dereferencing client callback mCallbackThread.stop(); Loading @@ -155,7 +158,7 @@ Return<void> NativeCallback::hardwareFailure() { } Return<void> NativeCallback::configChange(Result result, const BandConfig& config) { ALOGV("configChange(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([result, config, this](JNIEnv *env) { if (result == Result::OK) { Loading @@ -173,7 +176,7 @@ Return<void> NativeCallback::configChange(Result result, const BandConfig& confi } Return<void> NativeCallback::tuneComplete(Result result, const V1_0::ProgramInfo& info) { ALOGV("tuneComplete(%d)", result); ALOGV("%s(%d)", __func__, result); if (mHalRev > HalRevision::V1_0) { ALOGW("1.0 callback was ignored"); Loading @@ -185,7 +188,7 @@ Return<void> NativeCallback::tuneComplete(Result result, const V1_0::ProgramInfo } Return<void> NativeCallback::tuneComplete_1_1(Result result, const ProgramSelector& selector) { ALOGV("tuneComplete_1_1(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([result, this](JNIEnv *env) { if (result == Result::OK) { Loading @@ -201,17 +204,17 @@ Return<void> NativeCallback::tuneComplete_1_1(Result result, const ProgramSelect } Return<void> NativeCallback::afSwitch(const V1_0::ProgramInfo& info) { ALOGV("afSwitch()"); ALOGV("%s", __func__); return tuneComplete(Result::OK, info); } Return<void> NativeCallback::afSwitch_1_1(const ProgramSelector& selector) { ALOGV("afSwitch_1_1()"); ALOGV("%s", __func__); return tuneComplete_1_1(Result::OK, selector); } Return<void> NativeCallback::antennaStateChange(bool connected) { ALOGV("antennaStateChange(%d)", connected); ALOGV("%s(%d)", __func__, connected); mCallbackThread.enqueue([this, connected](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onAntennaState, connected); Loading @@ -221,7 +224,7 @@ Return<void> NativeCallback::antennaStateChange(bool connected) { } Return<void> NativeCallback::trafficAnnouncement(bool active) { ALOGV("trafficAnnouncement(%d)", active); ALOGV("%s(%d)", __func__, active); mCallbackThread.enqueue([this, active](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onTrafficAnnouncement, active); Loading @@ -231,7 +234,7 @@ Return<void> NativeCallback::trafficAnnouncement(bool active) { } Return<void> NativeCallback::emergencyAnnouncement(bool active) { ALOGV("emergencyAnnouncement(%d)", active); ALOGV("%s(%d)", __func__, active); mCallbackThread.enqueue([this, active](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onEmergencyAnnouncement, active); Loading @@ -243,7 +246,7 @@ Return<void> NativeCallback::emergencyAnnouncement(bool active) { Return<void> NativeCallback::newMetadata(uint32_t channel, uint32_t subChannel, const hidl_vec<MetaData>& metadata) { // channel and subChannel are not used ALOGV("newMetadata(%d, %d)", channel, subChannel); ALOGV("%s(%d, %d)", __func__, channel, subChannel); if (mHalRev > HalRevision::V1_0) { ALOGW("1.0 callback was ignored"); Loading @@ -258,7 +261,7 @@ Return<void> NativeCallback::newMetadata(uint32_t channel, uint32_t subChannel, } Return<void> NativeCallback::backgroundScanAvailable(bool isAvailable) { ALOGV("backgroundScanAvailable(%d)", isAvailable); ALOGV("%s(%d)", __func__, isAvailable); mCallbackThread.enqueue([this, isAvailable](JNIEnv *env) { env->CallVoidMethod(mJCallback, Loading @@ -269,7 +272,7 @@ Return<void> NativeCallback::backgroundScanAvailable(bool isAvailable) { } Return<void> NativeCallback::backgroundScanComplete(ProgramListResult result) { ALOGV("backgroundScanComplete(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([this, result](JNIEnv *env) { if (result == ProgramListResult::OK) { Loading @@ -285,7 +288,7 @@ Return<void> NativeCallback::backgroundScanComplete(ProgramListResult result) { } Return<void> NativeCallback::programListChanged() { ALOGV("programListChanged()"); ALOGV("%s", __func__); mCallbackThread.enqueue([this](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onProgramListChanged); Loading @@ -295,7 +298,7 @@ Return<void> NativeCallback::programListChanged() { } Return<void> NativeCallback::programInfoChanged() { ALOGV("programInfoChanged()"); ALOGV("%s", __func__); mCallbackThread.enqueue([this](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onProgramInfoChanged); Loading @@ -318,8 +321,8 @@ static TunerCallbackContext& getNativeContext(JNIEnv *env, jobject jTunerCb) { } static jlong nativeInit(JNIEnv *env, jobject obj, jobject jTuner, jint jHalRev) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto halRev = static_cast<HalRevision>(jHalRev); Loading @@ -331,16 +334,16 @@ static jlong nativeInit(JNIEnv *env, jobject obj, jobject jTuner, jint jHalRev) } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<TunerCallbackContext*>(nativeContext); delete ctx; } static void nativeDetach(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeDetach()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mNativeCallback == nullptr) return; Loading @@ -349,7 +352,7 @@ static void nativeDetach(JNIEnv *env, jobject obj, jlong nativeContext) { } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject jTunerCallback) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(env, jTunerCallback); return ctx.mNativeCallback; } Loading Loading
services/core/jni/BroadcastRadio/BroadcastRadioService.cpp +13 −10 Original line number Diff line number Diff line Loading @@ -27,14 +27,17 @@ #include <android/hidl/manager/1.0/IServiceManager.h> #include <core_jni_helpers.h> #include <hidl/ServiceManagement.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> #include <JNIHelp.h> namespace android { namespace server { namespace BroadcastRadio { namespace BroadcastRadioService { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_string; using hardware::hidl_vec; Loading @@ -50,7 +53,7 @@ using V1_0::ProgramInfo; using V1_0::MetaData; using V1_0::ITuner; static Mutex gContextMutex; static mutex gContextMutex; static struct { struct { Loading Loading @@ -90,8 +93,8 @@ static ServiceContext& getNativeContext(jlong nativeContextHandle) { } static jlong nativeInit(JNIEnv *env, jobject obj) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto nativeContext = new ServiceContext(); static_assert(sizeof(jlong) >= sizeof(nativeContext), "jlong is smaller than a pointer"); Loading @@ -99,16 +102,16 @@ static jlong nativeInit(JNIEnv *env, jobject obj) { } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<ServiceContext*>(nativeContext); delete ctx; } static jobject nativeLoadModules(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeLoadModules()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); // Get list of registered HIDL HAL implementations. Loading Loading @@ -182,8 +185,8 @@ static jobject nativeLoadModules(JNIEnv *env, jobject obj, jlong nativeContext) static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jint moduleId, jobject bandConfig, bool withAudio, jobject callback) { ALOGV("nativeOpenTuner()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (callback == nullptr) { Loading
services/core/jni/BroadcastRadio/NativeCallbackThread.cpp +25 −33 Original line number Diff line number Diff line Loading @@ -23,45 +23,38 @@ namespace android { NativeCallbackThread::NativeCallbackThread(JavaVM *vm) : mExitting(false), mvm(vm) { auto res = pthread_create(&mThread, nullptr, main, this); if (res != 0) { ALOGE("Couldn't start NativeCallbackThread"); mThread = 0; return; } using std::lock_guard; using std::mutex; using std::unique_lock; NativeCallbackThread::NativeCallbackThread(JavaVM *vm) : mvm(vm), mExiting(false), mThread(&NativeCallbackThread::threadLoop, this) { ALOGD("Started native callback thread %p", this); } NativeCallbackThread::~NativeCallbackThread() { ALOGV("~NativeCallbackThread %p", this); ALOGV("%s %p", __func__, this); stop(); } void* NativeCallbackThread::main(void *args) { auto self = reinterpret_cast<NativeCallbackThread*>(args); self->main(); return nullptr; } void NativeCallbackThread::main() { ALOGV("NativeCallbackThread::main()"); void NativeCallbackThread::threadLoop() { ALOGV("%s", __func__); JNIEnv *env = nullptr; JavaVMAttachArgs aargs = {JNI_VERSION_1_4, "NativeCallbackThread", nullptr}; if (mvm->AttachCurrentThread(&env, &aargs) != JNI_OK || env == nullptr) { ALOGE("Couldn't attach thread"); mExiting = true; return; } while (!mExitting) { while (!mExiting) { ALOGV("Waiting for task..."); Task task; { AutoMutex _l(mQueueMutex); auto res = mQueueCond.wait(mQueueMutex); ALOGE_IF(res != 0, "Wait failed: %d", res); if (mExitting || res != 0) break; unique_lock<mutex> lk(mQueueMutex); mQueueCond.wait(lk); if (mExiting) break; if (mQueue.empty()) continue; task = mQueue.front(); Loading @@ -84,36 +77,35 @@ void NativeCallbackThread::main() { } void NativeCallbackThread::enqueue(const Task &task) { AutoMutex _l(mQueueMutex); lock_guard<mutex> lk(mQueueMutex); if (mThread == 0 || mExitting) { if (mExiting) { ALOGW("Callback thread %p is not serving calls", this); return; } mQueue.push(task); mQueueCond.signal(); mQueueCond.notify_one(); } void NativeCallbackThread::stop() { ALOGV("stop() %p", this); ALOGV("%s %p", __func__, this); { AutoMutex _l(mQueueMutex); lock_guard<mutex> lk(mQueueMutex); if (mThread == 0 || mExitting) return; if (mExiting) return; mExitting = true; mQueueCond.signal(); mExiting = true; mQueueCond.notify_one(); } if (pthread_self() == mThread) { if (mThread.get_id() == std::thread::id()) { // you can't self-join a thread, but it's ok when calling from our sub-task ALOGD("About to stop native callback thread %p", this); mThread.detach(); } else { auto ret = pthread_join(mThread, nullptr); ALOGE_IF(ret != 0, "Couldn't join thread: %d", ret); mThread.join(); ALOGD("Stopped native callback thread %p", this); } } Loading
services/core/jni/BroadcastRadio/NativeCallbackThread.h +7 −10 Original line number Diff line number Diff line Loading @@ -20,26 +20,23 @@ #include <android-base/macros.h> #include <functional> #include <jni.h> #include <pthread.h> #include <queue> #include <utils/Condition.h> #include <utils/Mutex.h> #include <thread> namespace android { class NativeCallbackThread { typedef std::function<void(JNIEnv*)> Task; pthread_t mThread; Mutex mQueueMutex; Condition mQueueCond; std::atomic<bool> mExitting; JavaVM *mvm; std::queue<Task> mQueue; static void* main(void *args); void main(); std::mutex mQueueMutex; std::condition_variable mQueueCond; std::atomic<bool> mExiting; std::thread mThread; void threadLoop(); DISALLOW_COPY_AND_ASSIGN(NativeCallbackThread); Loading
services/core/jni/BroadcastRadio/Tuner.cpp +35 −29 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ #include "convert.h" #include "TunerCallback.h" #include <JNIHelp.h> #include <Utils.h> #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h> #include <binder/IPCThreadState.h> #include <broadcastradio-utils/Utils.h> #include <core_jni_helpers.h> #include <media/AudioSystem.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> namespace android { Loading @@ -35,6 +35,9 @@ namespace server { namespace BroadcastRadio { namespace Tuner { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_death_recipient; using hardware::hidl_vec; Loading @@ -49,7 +52,7 @@ using V1_0::Result; using V1_1::ITunerCallback; using V1_1::ProgramListResult; static Mutex gContextMutex; static mutex gContextMutex; static struct { struct { Loading Loading @@ -106,8 +109,8 @@ static TunerContext& getNativeContext(JNIEnv *env, JavaRef<jobject> const &jTune } static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev, bool withAudio, jint band) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = new TunerContext(); ctx->mHalRev = static_cast<HalRevision>(halRev); Loading @@ -119,8 +122,8 @@ static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev, bool withAudio, j } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<TunerContext*>(nativeContext); delete ctx; Loading Loading @@ -150,10 +153,9 @@ static void notifyAudioService(TunerContext& ctx, bool connected) { void assignHalInterfaces(JNIEnv *env, JavaRef<jobject> const &jTuner, sp<V1_0::IBroadcastRadio> halModule, sp<V1_0::ITuner> halTuner) { ALOGV("setHalTuner(%p)", halTuner.get()); ALOGV("%s(%p)", __func__, halTuner.get()); ALOGE_IF(halTuner == nullptr, "HAL tuner is a nullptr"); AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(env, jTuner); if (ctx.mIsClosed) { Loading Loading @@ -187,12 +189,12 @@ static sp<V1_0::ITuner> getHalTuner(const TunerContext& ctx) { } sp<V1_0::ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); return getHalTuner(getNativeContext(nativeContext)); } sp<V1_1::ITuner> getHalTuner11(jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); return getNativeContext(nativeContext).mHalTuner11; } Loading @@ -206,8 +208,9 @@ Region getRegion(JNIEnv *env, jobject obj) { } static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mIsClosed) return; ctx.mIsClosed = true; Loading @@ -228,9 +231,10 @@ static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner = getHalTuner(ctx); if (halTuner == nullptr) return; Loading @@ -244,7 +248,7 @@ static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, Region region) { ALOGV("nativeSetConfiguration()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return nullptr; Loading @@ -263,7 +267,7 @@ static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeCont static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeStep()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -273,7 +277,7 @@ static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeScan()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -282,9 +286,10 @@ static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, } static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jobject jSelector) { ALOGV("nativeTune()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner10 = getHalTuner(ctx); auto halTuner11 = ctx.mHalTuner11; if (halTuner10 == nullptr) return; Loading @@ -304,7 +309,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jobject jS } static void nativeCancel(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeCancel()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Loading @@ -323,9 +328,10 @@ static void nativeCancelAnnouncement(JNIEnv *env, jobject obj, jlong nativeConte } static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeGetProgramInformation()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); auto halTuner10 = getHalTuner(ctx); auto halTuner11 = ctx.mHalTuner11; if (halTuner10 == nullptr) return nullptr; Loading Loading @@ -355,7 +361,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ } static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeStartBackgroundScan()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { ALOGI("Background scan is not supported with HAL < 1.1"); Loading @@ -369,7 +375,7 @@ static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeCont } static jobject nativeGetProgramList(JNIEnv *env, jobject obj, jlong nativeContext, jstring jFilter) { ALOGV("nativeGetProgramList()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { ALOGI("Program list is not supported with HAL < 1.1"); Loading Loading @@ -398,7 +404,7 @@ static jobject nativeGetProgramList(JNIEnv *env, jobject obj, jlong nativeContex static jbyteArray nativeGetImage(JNIEnv *env, jobject obj, jlong nativeContext, jint id) { ALOGV("%s(%x)", __func__, id); AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mHalModule11 == nullptr) { Loading Loading @@ -435,7 +441,7 @@ static jbyteArray nativeGetImage(JNIEnv *env, jobject obj, jlong nativeContext, } static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeIsAnalogForced()"); ALOGV("%s", __func__); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", Loading @@ -456,7 +462,7 @@ static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) } static void nativeSetAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext, bool isForced) { ALOGV("nativeSetAnalogForced()"); ALOGV("%s(%d)", __func__, isForced); auto halTuner = getHalTuner11(nativeContext); if (halTuner == nullptr) { jniThrowException(env, "java/lang/IllegalStateException", Loading @@ -469,7 +475,7 @@ static void nativeSetAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext, } static bool nativeIsAntennaConnected(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeIsAntennaConnected()"); ALOGV("%s", __func__); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return false; Loading
services/core/jni/BroadcastRadio/TunerCallback.cpp +28 −25 Original line number Diff line number Diff line Loading @@ -22,9 +22,9 @@ #include "Tuner.h" #include "convert.h" #include <JNIHelp.h> #include <Utils.h> #include <broadcastradio-utils/Utils.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <utils/Log.h> namespace android { Loading @@ -32,6 +32,9 @@ namespace server { namespace BroadcastRadio { namespace TunerCallback { using std::lock_guard; using std::mutex; using hardware::Return; using hardware::hidl_vec; Loading Loading @@ -76,7 +79,7 @@ enum class TunerError : jint { BACKGROUND_SCAN_FAILED = 6, }; static Mutex gContextMutex; static mutex gContextMutex; class NativeCallback : public ITunerCallback { jobject mJTuner; Loading Loading @@ -122,13 +125,13 @@ private: NativeCallback::NativeCallback(JNIEnv *env, jobject jTuner, jobject jCallback, HalRevision halRev) : mCallbackThread(gvm), mHalRev(halRev) { ALOGV("NativeCallback()"); ALOGV("%s", __func__); mJTuner = env->NewGlobalRef(jTuner); mJCallback = env->NewGlobalRef(jCallback); } NativeCallback::~NativeCallback() { ALOGV("~NativeCallback()"); ALOGV("%s", __func__); // stop callback thread before dereferencing client callback mCallbackThread.stop(); Loading @@ -155,7 +158,7 @@ Return<void> NativeCallback::hardwareFailure() { } Return<void> NativeCallback::configChange(Result result, const BandConfig& config) { ALOGV("configChange(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([result, config, this](JNIEnv *env) { if (result == Result::OK) { Loading @@ -173,7 +176,7 @@ Return<void> NativeCallback::configChange(Result result, const BandConfig& confi } Return<void> NativeCallback::tuneComplete(Result result, const V1_0::ProgramInfo& info) { ALOGV("tuneComplete(%d)", result); ALOGV("%s(%d)", __func__, result); if (mHalRev > HalRevision::V1_0) { ALOGW("1.0 callback was ignored"); Loading @@ -185,7 +188,7 @@ Return<void> NativeCallback::tuneComplete(Result result, const V1_0::ProgramInfo } Return<void> NativeCallback::tuneComplete_1_1(Result result, const ProgramSelector& selector) { ALOGV("tuneComplete_1_1(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([result, this](JNIEnv *env) { if (result == Result::OK) { Loading @@ -201,17 +204,17 @@ Return<void> NativeCallback::tuneComplete_1_1(Result result, const ProgramSelect } Return<void> NativeCallback::afSwitch(const V1_0::ProgramInfo& info) { ALOGV("afSwitch()"); ALOGV("%s", __func__); return tuneComplete(Result::OK, info); } Return<void> NativeCallback::afSwitch_1_1(const ProgramSelector& selector) { ALOGV("afSwitch_1_1()"); ALOGV("%s", __func__); return tuneComplete_1_1(Result::OK, selector); } Return<void> NativeCallback::antennaStateChange(bool connected) { ALOGV("antennaStateChange(%d)", connected); ALOGV("%s(%d)", __func__, connected); mCallbackThread.enqueue([this, connected](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onAntennaState, connected); Loading @@ -221,7 +224,7 @@ Return<void> NativeCallback::antennaStateChange(bool connected) { } Return<void> NativeCallback::trafficAnnouncement(bool active) { ALOGV("trafficAnnouncement(%d)", active); ALOGV("%s(%d)", __func__, active); mCallbackThread.enqueue([this, active](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onTrafficAnnouncement, active); Loading @@ -231,7 +234,7 @@ Return<void> NativeCallback::trafficAnnouncement(bool active) { } Return<void> NativeCallback::emergencyAnnouncement(bool active) { ALOGV("emergencyAnnouncement(%d)", active); ALOGV("%s(%d)", __func__, active); mCallbackThread.enqueue([this, active](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onEmergencyAnnouncement, active); Loading @@ -243,7 +246,7 @@ Return<void> NativeCallback::emergencyAnnouncement(bool active) { Return<void> NativeCallback::newMetadata(uint32_t channel, uint32_t subChannel, const hidl_vec<MetaData>& metadata) { // channel and subChannel are not used ALOGV("newMetadata(%d, %d)", channel, subChannel); ALOGV("%s(%d, %d)", __func__, channel, subChannel); if (mHalRev > HalRevision::V1_0) { ALOGW("1.0 callback was ignored"); Loading @@ -258,7 +261,7 @@ Return<void> NativeCallback::newMetadata(uint32_t channel, uint32_t subChannel, } Return<void> NativeCallback::backgroundScanAvailable(bool isAvailable) { ALOGV("backgroundScanAvailable(%d)", isAvailable); ALOGV("%s(%d)", __func__, isAvailable); mCallbackThread.enqueue([this, isAvailable](JNIEnv *env) { env->CallVoidMethod(mJCallback, Loading @@ -269,7 +272,7 @@ Return<void> NativeCallback::backgroundScanAvailable(bool isAvailable) { } Return<void> NativeCallback::backgroundScanComplete(ProgramListResult result) { ALOGV("backgroundScanComplete(%d)", result); ALOGV("%s(%d)", __func__, result); mCallbackThread.enqueue([this, result](JNIEnv *env) { if (result == ProgramListResult::OK) { Loading @@ -285,7 +288,7 @@ Return<void> NativeCallback::backgroundScanComplete(ProgramListResult result) { } Return<void> NativeCallback::programListChanged() { ALOGV("programListChanged()"); ALOGV("%s", __func__); mCallbackThread.enqueue([this](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onProgramListChanged); Loading @@ -295,7 +298,7 @@ Return<void> NativeCallback::programListChanged() { } Return<void> NativeCallback::programInfoChanged() { ALOGV("programInfoChanged()"); ALOGV("%s", __func__); mCallbackThread.enqueue([this](JNIEnv *env) { env->CallVoidMethod(mJCallback, gjni.TunerCallback.onProgramInfoChanged); Loading @@ -318,8 +321,8 @@ static TunerCallbackContext& getNativeContext(JNIEnv *env, jobject jTunerCb) { } static jlong nativeInit(JNIEnv *env, jobject obj, jobject jTuner, jint jHalRev) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto halRev = static_cast<HalRevision>(jHalRev); Loading @@ -331,16 +334,16 @@ static jlong nativeInit(JNIEnv *env, jobject obj, jobject jTuner, jint jHalRev) } static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeFinalize()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto ctx = reinterpret_cast<TunerCallbackContext*>(nativeContext); delete ctx; } static void nativeDetach(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeDetach()"); AutoMutex _l(gContextMutex); ALOGV("%s", __func__); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mNativeCallback == nullptr) return; Loading @@ -349,7 +352,7 @@ static void nativeDetach(JNIEnv *env, jobject obj, jlong nativeContext) { } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject jTunerCallback) { AutoMutex _l(gContextMutex); lock_guard<mutex> lk(gContextMutex); auto& ctx = getNativeContext(env, jTunerCallback); return ctx.mNativeCallback; } Loading