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

Commit 37d986d1 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Implement tune, cancel and getProgramInformation calls of ITuner.

Test: instrumentation
Bug: b/36863239
Change-Id: I7c0faacec7beccddc29f3f207ba6a166cb53e60c
parent daca7890
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -29,8 +29,6 @@ interface ITuner {

    RadioManager.BandConfig getConfiguration();

    int getProgramInformation(out RadioManager.ProgramInfo[] infoOut);

    /**
     * @throws IllegalStateException if tuner was opened without audio
     */
@@ -58,4 +56,6 @@ interface ITuner {
     * @throws IllegalStateException if called out of sequence
     */
    void cancel();

    RadioManager.ProgramInfo getProgramInformation();
}
+25 −5
Original line number Diff line number Diff line
@@ -137,14 +137,33 @@ class TunerAdapter extends RadioTuner {

    @Override
    public int tune(int channel, int subChannel) {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            mTuner.tune(channel, subChannel);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Can't tune", e);
            return RadioManager.STATUS_INVALID_OPERATION;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Can't tune", e);
            return RadioManager.STATUS_BAD_VALUE;
        } catch (RemoteException e) {
            Log.e(TAG, "service died", e);
            return RadioManager.STATUS_DEAD_OBJECT;
        }
        return RadioManager.STATUS_OK;
    }

    @Override
    public int cancel() {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            mTuner.cancel();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Can't cancel", e);
            return RadioManager.STATUS_INVALID_OPERATION;
        } catch (RemoteException e) {
            Log.e(TAG, "service died", e);
            return RadioManager.STATUS_DEAD_OBJECT;
        }
        return RadioManager.STATUS_OK;
    }

    @Override
@@ -153,7 +172,8 @@ class TunerAdapter extends RadioTuner {
            throw new IllegalArgumentException("The argument must be an array of length 1");
        }
        try {
            return mTuner.getProgramInformation(info);
            info[0] = mTuner.getProgramInformation();
            return RadioManager.STATUS_OK;
        } catch (RemoteException e) {
            Log.e(TAG, "service died", e);
            return RadioManager.STATUS_DEAD_OBJECT;
+9 −9
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ class Tuner extends ITuner.Stub {
    private native void nativeTune(long nativeContext, int channel, int subChannel);
    private native void nativeCancel(long nativeContext);

    private native RadioManager.ProgramInfo nativeGetProgramInformation(long nativeContext);

    @Override
    public void close() {
        synchronized (mLock) {
@@ -86,15 +88,6 @@ class Tuner extends ITuner.Stub {
        }
    }

    @Override
    public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) {
        if (infoOut == null || infoOut.length != 1) {
            throw new IllegalArgumentException("The argument must be an array of length 1");
        }
        Slog.d(TAG, "getProgramInformation()");
        return RadioManager.STATUS_INVALID_OPERATION;
    }

    @Override
    public void setMuted(boolean mute) {
        if (!mWithAudio) {
@@ -147,4 +140,11 @@ class Tuner extends ITuner.Stub {
            nativeCancel(mNativeContext);
        }
    }

    @Override
    public RadioManager.ProgramInfo getProgramInformation() {
        synchronized (mLock) {
            return nativeGetProgramInformation(mNativeContext);
        }
    }
}
+57 −11
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ namespace V1_0 = hardware::broadcastradio::V1_0;
namespace V1_1 = hardware::broadcastradio::V1_1;

using V1_0::BandConfig;
using V1_0::ITuner;
using V1_0::MetaData;
using V1_0::Result;
using V1_1::ITunerCallback;
@@ -57,7 +56,9 @@ static struct {
struct TunerContext {
    TunerContext() {}

    sp<ITuner> mHalTuner;
    HalRevision mHalRev;
    sp<V1_0::ITuner> mHalTuner;
    sp<V1_1::ITuner> mHalTuner11;
    sp<TunerCallback> mNativeCallback;

private:
@@ -82,8 +83,8 @@ static jlong nativeInit(JNIEnv *env, jobject obj, jobject clientCallback, jint h
    AutoMutex _l(gContextMutex);

    auto ctx = new TunerContext();
    ctx->mNativeCallback = new TunerCallback(env, obj,
            clientCallback, static_cast<HalRevision>(halRev));
    ctx->mHalRev = static_cast<HalRevision>(halRev);
    ctx->mNativeCallback = new TunerCallback(env, obj, clientCallback, ctx->mHalRev);

    static_assert(sizeof(jlong) >= sizeof(ctx), "jlong is smaller than a pointer");
    return reinterpret_cast<jlong>(ctx);
@@ -97,22 +98,33 @@ static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) {
    delete ctx;
}

void setHalTuner(JNIEnv *env, jobject obj, sp<ITuner> halTuner) {
void setHalTuner(JNIEnv *env, jobject obj, sp<V1_0::ITuner> halTuner) {
    ALOGV("setHalTuner(%p)", halTuner.get());
    ALOGE_IF(halTuner == nullptr, "HAL tuner is a nullptr");

    AutoMutex _l(gContextMutex);
    auto& ctx = getNativeContext(env, obj);

    ctx.mHalTuner = halTuner;
    ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr);
    ALOGW_IF(ctx.mHalRev >= HalRevision::V1_1 && ctx.mHalTuner11 == nullptr,
            "Provided tuner does not implement 1.1 HAL");
}

sp<ITuner> getHalTuner(jlong nativeContext) {
sp<V1_0::ITuner> getHalTuner(jlong nativeContext) {
    AutoMutex _l(gContextMutex);
    auto tuner = getNativeContext(nativeContext).mHalTuner;
    LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set");
    return tuner;
}

sp<V1_1::ITuner> getHalTuner11(jlong nativeContext) {
    AutoMutex _l(gContextMutex);
    auto tuner = getNativeContext(nativeContext).mHalTuner11;
    LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set");
    return tuner;
}

sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) {
    AutoMutex _l(gContextMutex);
    auto& ctx = getNativeContext(env, obj);
@@ -128,6 +140,7 @@ static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) {
    auto& ctx = getNativeContext(nativeContext);
    ALOGI("Closing tuner %p", ctx.mHalTuner.get());
    ctx.mNativeCallback->detach();
    ctx.mHalTuner11 = nullptr;
    ctx.mHalTuner = nullptr;
    ctx.mNativeCallback = nullptr;
}
@@ -153,7 +166,7 @@ static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeCont
        halResult = result;
        halConfig = config;
    });
    if (convert::ThrowIfFailed(env, hidlResult)) {
    if (convert::ThrowIfFailed(env, hidlResult, halResult)) {
        return nullptr;
    }

@@ -180,13 +193,44 @@ static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext,

static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext,
        jint channel, jint subChannel) {
    // TODO(b/36863239): implement
    jniThrowException(env, "java/lang/RuntimeException", "not implemented yet");
    ALOGV("nativeTune(%d, %d)", channel, subChannel);
    auto halTuner = getHalTuner(nativeContext);

    convert::ThrowIfFailed(env, halTuner->tune(channel, subChannel));
}

static void nativeCancel(JNIEnv *env, jobject obj, jlong nativeContext) {
    // TODO(b/36863239): implement
    jniThrowException(env, "java/lang/RuntimeException", "not implemented yet");
    ALOGV("nativeCancel()");
    auto halTuner = getHalTuner(nativeContext);

    convert::ThrowIfFailed(env, halTuner->cancel());
}

static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativeContext) {
    ALOGV("nativeGetProgramInformation()");
    auto halTuner10 = getHalTuner(nativeContext);
    auto halTuner11 = getHalTuner11(nativeContext);

    V1_1::ProgramInfo halInfo;
    Result halResult;
    Return<void> hidlResult;
    if (halTuner11 != nullptr) {
        hidlResult = halTuner11->getProgramInformation_1_1([&](Result result,
                const V1_1::ProgramInfo& info) {
            halResult = result;
            halInfo = info;
        });
    } else {
        hidlResult = halTuner10->getProgramInformation([&](Result result,
                const V1_0::ProgramInfo& info) {
            halResult = result;
            halInfo.base = info;
        });
    }

    if (convert::ThrowIfFailed(env, hidlResult, halResult)) return nullptr;

    return convert::ProgramInfoFromHal(env, halInfo).release();
}

static const JNINativeMethod gTunerMethods[] = {
@@ -201,6 +245,8 @@ static const JNINativeMethod gTunerMethods[] = {
    { "nativeScan", "(JZZ)V", (void*)nativeScan },
    { "nativeTune", "(JII)V", (void*)nativeTune },
    { "nativeCancel", "(J)V", (void*)nativeCancel },
    { "nativeGetProgramInformation", "(J)Landroid/hardware/radio/RadioManager$ProgramInfo;",
            (void*)nativeGetProgramInformation },
};

} // namespace Tuner
+13 −11
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static struct {
} gjni;

template <typename T>
bool ThrowIfFailedCommon(JNIEnv *env, const hardware::Return<T> &hidlResult) {
static bool ThrowIfFailedHidl(JNIEnv *env, const Return<T> &hidlResult) {
    if (hidlResult.isOk()) return false;

    jniThrowExceptionFmt(env, "java/lang/RuntimeException",
@@ -89,15 +89,8 @@ bool ThrowIfFailedCommon(JNIEnv *env, const hardware::Return<T> &hidlResult) {
    return true;
}

bool ThrowIfFailed(JNIEnv *env, const hardware::Return<void> &hidlResult) {
    return ThrowIfFailedCommon(env, hidlResult);
}

bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult) {
    if (ThrowIfFailedCommon(env, hidlResult)) return true;

    Result result = hidlResult;
    switch (result) {
static bool ThrowIfFailed(JNIEnv *env, const Result halResult) {
    switch (halResult) {
        case Result::OK:
            return false;
        case Result::NOT_INITIALIZED:
@@ -116,11 +109,20 @@ bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult
            return true;
        default:
            jniThrowExceptionFmt(env, "java/lang/RuntimeException",
                    "Unknown failure, result: %d", result);
                    "Unknown failure, result: %d", halResult);
            return true;
    }
}

bool ThrowIfFailed(JNIEnv *env, const Return<void> &hidlResult, Result halResult) {
    return ThrowIfFailedHidl(env, hidlResult) || ThrowIfFailed(env, halResult);
}

bool ThrowIfFailed(JNIEnv *env, const Return<Result> &hidlResult) {
    return ThrowIfFailedHidl(env, hidlResult)
            || ThrowIfFailed(env, static_cast<Result>(hidlResult));
}

static Rds RdsForRegion(bool rds, Region region) {
    if (!rds) return Rds::NONE;

Loading