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

Commit d3d53f66 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Implement program list and forced analog features of ITuner.

Test: instrumentation
Bug: b/36863239
Change-Id: Ib900a444f36d33dc9d55a99e699f9b6ce0c943ad
parent 5649d3e9
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -58,4 +58,30 @@ interface ITuner {
    void cancel();

    RadioManager.ProgramInfo getProgramInformation();

    /**
     * @returns {@code true} if the scan was properly scheduled,
     *          {@code false} if the scan feature is unavailable
     */
    boolean startBackgroundScan();

    /**
     * @returns the list, or null if scan is in progress
     * @throws IllegalArgumentException if invalid arguments are passed
     * @throws IllegalStateException if the scan has not been started, client may
     *         call startBackgroundScan to fix this.
     */
    List<RadioManager.ProgramInfo> getProgramList(String filter);

    /**
     * @throws IllegalStateException if the switch is not supported at current
     *         configuration.
     */
    boolean isAnalogForced();

    /**
     * @throws IllegalStateException if the switch is not supported at current
     *         configuration.
     */
    void setAnalogForced(boolean isForced);
}
+20 −8
Original line number Diff line number Diff line
@@ -182,26 +182,38 @@ class TunerAdapter extends RadioTuner {

    @Override
    public boolean startBackgroundScan() {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            return mTuner.startBackgroundScan();
        } catch (RemoteException e) {
            throw new RuntimeException("service died", e);
        }
    }

    @Override
    public @NonNull List<RadioManager.ProgramInfo> getProgramList(@Nullable String filter) {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            return mTuner.getProgramList(filter);
        } catch (RemoteException e) {
            throw new RuntimeException("service died", e);
        }
    }

    @Override
    public boolean isAnalogForced() {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            return mTuner.isAnalogForced();
        } catch (RemoteException e) {
            throw new RuntimeException("service died", e);
        }
    }

    @Override
    public void setAnalogForced(boolean isForced) {
        // TODO(b/36863239): forward to mTuner
        throw new RuntimeException("Not implemented");
        try {
            mTuner.setAnalogForced(isForced);
        } catch (RemoteException e) {
            throw new RuntimeException("service died", e);
        }
    }

    @Override
+40 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
import android.util.Slog;

import java.util.List;

class Tuner extends ITuner.Stub {
    // TODO(b/36863239): rename to RadioService.Tuner when native service goes away
    private static final String TAG = "RadioServiceJava.Tuner";
@@ -65,6 +67,12 @@ class Tuner extends ITuner.Stub {
    private native void nativeCancel(long nativeContext);

    private native RadioManager.ProgramInfo nativeGetProgramInformation(long nativeContext);
    private native boolean nativeStartBackgroundScan(long nativeContext);
    private native List<RadioManager.ProgramInfo> nativeGetProgramList(long nativeContext,
            String filter);

    private native boolean nativeIsAnalogForced(long nativeContext);
    private native void nativeSetAnalogForced(long nativeContext, boolean isForced);

    @Override
    public void close() {
@@ -168,4 +176,36 @@ class Tuner extends ITuner.Stub {
            return nativeGetProgramInformation(mNativeContext);
        }
    }

    public boolean startBackgroundScan() {
        synchronized (mLock) {
            checkNotClosedLocked();
            return nativeStartBackgroundScan(mNativeContext);
        }
    }

    public List<RadioManager.ProgramInfo> getProgramList(String filter) {
        synchronized (mLock) {
            checkNotClosedLocked();
            List<RadioManager.ProgramInfo> list = nativeGetProgramList(mNativeContext, filter);
            if (list == null) {
                throw new IllegalStateException("Program list is not ready");
            }
            return list;
        }
    }

    public boolean isAnalogForced() {
        synchronized (mLock) {
            checkNotClosedLocked();
            return nativeIsAnalogForced(mNativeContext);
        }
    }

    public void setAnalogForced(boolean isForced) {
        synchronized (mLock) {
            checkNotClosedLocked();
            nativeSetAnalogForced(mNativeContext, isForced);
        }
    }
}
+0 −7
Original line number Diff line number Diff line
@@ -54,10 +54,6 @@ static struct {
        jclass clazz;
        jmethodID cstor;
    } Tuner;

    struct {
        jclass clazz;
    } RadioService;
} gjni;

struct ServiceContext {
@@ -204,9 +200,6 @@ void register_android_server_radio_RadioService(JNIEnv *env) {
    gjni.Tuner.cstor = GetMethodIDOrDie(env, tunerClass, "<init>",
            "(Landroid/hardware/radio/ITunerCallback;IIZ)V");

    auto serviceClass = FindClassOrDie(env, "com/android/server/radio/RadioService");
    gjni.RadioService.clazz = MakeGlobalRefOrDie(env, serviceClass);

    auto res = jniRegisterNativeMethods(env, "com/android/server/radio/RadioService",
            gRadioServiceMethods, NELEM(gRadioServiceMethods));
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+92 −0
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@ using V1_1::ProgramListResult;
static Mutex gContextMutex;

static struct {
    struct {
        jclass clazz;
        jmethodID cstor;
        jmethodID add;
    } ArrayList;
    struct {
        jfieldID nativeContext;
        jfieldID region;
@@ -235,6 +240,83 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ
    return convert::ProgramInfoFromHal(env, halInfo).release();
}

static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeContext) {
    ALOGV("nativeStartBackgroundScan()");
    auto halTuner = getHalTuner11(nativeContext);
    if (halTuner == nullptr) {
        ALOGI("Background scan is not supported with HAL < 1.1");
        return false;
    }

    auto halResult = halTuner->startBackgroundScan();

    if (halResult.isOk() && halResult == ProgramListResult::UNAVAILABLE) return false;
    return !convert::ThrowIfFailed(env, halResult);
}

static jobject nativeGetProgramList(JNIEnv *env, jobject obj, jlong nativeContext, jstring jFilter) {
    ALOGV("nativeGetProgramList()");
    EnvWrapper wrap(env);
    auto halTuner = getHalTuner11(nativeContext);
    if (halTuner == nullptr) {
        ALOGI("Program list is not supported with HAL < 1.1");
        return nullptr;
    }

    JavaRef<jobject> jList;
    ProgramListResult halResult = ProgramListResult::NOT_INITIALIZED;
    auto filter = env->GetStringUTFChars(jFilter, nullptr);
    auto hidlResult = halTuner->getProgramList(filter,
            [&](ProgramListResult result, const hidl_vec<V1_1::ProgramInfo>& programList) {
        halResult = result;
        if (halResult != ProgramListResult::OK) return;

        jList = wrap(env->NewObject(gjni.ArrayList.clazz, gjni.ArrayList.cstor));
        for (auto& program : programList) {
            auto jProgram = convert::ProgramInfoFromHal(env, program);
            env->CallBooleanMethod(jList.get(), gjni.ArrayList.add, jProgram.get());
        }
    });

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

    return jList.release();
}

static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) {
    ALOGV("nativeIsAnalogForced()");
    auto halTuner = getHalTuner11(nativeContext);
    if (halTuner == nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "Forced analog switch is not supported with HAL < 1.1");
        return false;
    }

    bool isForced;
    Result halResult;
    auto hidlResult = halTuner->isAnalogForced([&](Result result, bool isForcedRet) {
        halResult = result;
        isForced = isForcedRet;
    });

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

    return isForced;
}

static void nativeSetAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext, bool isForced) {
    ALOGV("nativeSetAnalogForced()");
    auto halTuner = getHalTuner11(nativeContext);
    if (halTuner == nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "Forced analog switch is not supported with HAL < 1.1");
        return;
    }

    auto halResult = halTuner->setAnalogForced(isForced);
    convert::ThrowIfFailed(env, halResult);
}

static const JNINativeMethod gTunerMethods[] = {
    { "nativeInit", "(I)J", (void*)nativeInit },
    { "nativeFinalize", "(J)V", (void*)nativeFinalize },
@@ -249,6 +331,11 @@ static const JNINativeMethod gTunerMethods[] = {
    { "nativeCancel", "(J)V", (void*)nativeCancel },
    { "nativeGetProgramInformation", "(J)Landroid/hardware/radio/RadioManager$ProgramInfo;",
            (void*)nativeGetProgramInformation },
    { "nativeStartBackgroundScan", "(J)Z", (void*)nativeStartBackgroundScan },
    { "nativeGetProgramList", "(JLjava/lang/String;)Ljava/util/List;",
            (void*)nativeGetProgramList },
    { "nativeIsAnalogForced", "(J)Z", (void*)nativeIsAnalogForced },
    { "nativeSetAnalogForced", "(JZ)V", (void*)nativeSetAnalogForced },
};

} // namespace Tuner
@@ -266,6 +353,11 @@ void register_android_server_radio_Tuner(JavaVM *vm, JNIEnv *env) {
    gjni.Tuner.tunerCallback = GetFieldIDOrDie(env, tunerClass, "mTunerCallback",
            "Lcom/android/server/radio/TunerCallback;");

    auto arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
    gjni.ArrayList.clazz = MakeGlobalRefOrDie(env, arrayListClass);
    gjni.ArrayList.cstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
    gjni.ArrayList.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");

    auto res = jniRegisterNativeMethods(env, "com/android/server/radio/Tuner",
            gTunerMethods, NELEM(gTunerMethods));
    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
Loading