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

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

Implement listing broadcast radio modules.

This provides support for other radio modules than default HAL.

Bug: b/36863239
Bug: b/32621196
Test: instrumentation
Change-Id: I92632597652c35b68f10d13b1ed6931fb49af0b2
parent 40ce3009
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.hardware.radio.RadioManager;
 * {@hide}
 */
interface IRadioService {
    List<RadioManager.ModuleProperties> listModules();

    ITuner openTuner(int moduleId, in RadioManager.BandConfig bandConfig, boolean withAudio,
            in ITunerCallback callback);
}
+5 −2
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package android.hardware.radio;

/** @hide */
parcelable RadioManager.ProgramInfo;
parcelable RadioManager.BandConfig;

/** @hide */
parcelable RadioManager.BandConfig;
parcelable RadioManager.ModuleProperties;

/** @hide */
parcelable RadioManager.ProgramInfo;
+55 −7
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@ import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;

import java.util.List;
import java.util.Arrays;
import java.util.List;

/**
 * The RadioManager class allows to control a broadcast radio tuner present on the device.
@@ -111,6 +111,7 @@ public class RadioManager {
    public static class ModuleProperties implements Parcelable {

        private final int mId;
        @NonNull private final String mServiceName;
        private final int mClassId;
        private final String mImplementor;
        private final String mProduct;
@@ -123,10 +124,12 @@ public class RadioManager {
        private final boolean mIsBgScanSupported;
        private final String mVendorExension;

        ModuleProperties(int id, int classId, String implementor, String product, String version,
                String serial, int numTuners, int numAudioSources, boolean isCaptureSupported,
                BandDescriptor[] bands, boolean isBgScanSupported, String vendorExension) {
        ModuleProperties(int id, String serviceName, int classId, String implementor,
                String product, String version, String serial, int numTuners, int numAudioSources,
                boolean isCaptureSupported, BandDescriptor[] bands, boolean isBgScanSupported,
                String vendorExension) {
            mId = id;
            mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName;
            mClassId = classId;
            mImplementor = implementor;
            mProduct = product;
@@ -149,6 +152,16 @@ public class RadioManager {
            return mId;
        }

        /**
         * Module service (driver) name as registered with HIDL.
         * @return the module service name.
         *
         * @hide FutureFeature
         */
        public @NonNull String getServiceName() {
            return mServiceName;
        }

        /** Module class identifier: {@link #CLASS_AM_FM}, {@link #CLASS_SAT}, {@link #CLASS_DT}
         * @return the radio module class identifier.
         */
@@ -250,6 +263,8 @@ public class RadioManager {

        private ModuleProperties(Parcel in) {
            mId = in.readInt();
            String serviceName = in.readString();
            mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName;
            mClassId = in.readInt();
            mImplementor = in.readString();
            mProduct = in.readString();
@@ -281,6 +296,7 @@ public class RadioManager {
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mId);
            dest.writeString(mServiceName);
            dest.writeInt(mClassId);
            dest.writeString(mImplementor);
            dest.writeString(mProduct);
@@ -301,7 +317,8 @@ public class RadioManager {

        @Override
        public String toString() {
            return "ModuleProperties [mId=" + mId + ", mClassId=" + mClassId
            return "ModuleProperties [mId=" + mId
                    + ", mServiceName=" + mServiceName + ", mClassId=" + mClassId
                    + ", mImplementor=" + mImplementor + ", mProduct=" + mProduct
                    + ", mVersion=" + mVersion + ", mSerial=" + mSerial
                    + ", mNumTuners=" + mNumTuners
@@ -316,6 +333,7 @@ public class RadioManager {
            final int prime = 31;
            int result = 1;
            result = prime * result + mId;
            result = prime * result + mServiceName.hashCode();
            result = prime * result + mClassId;
            result = prime * result + ((mImplementor == null) ? 0 : mImplementor.hashCode());
            result = prime * result + ((mProduct == null) ? 0 : mProduct.hashCode());
@@ -339,6 +357,7 @@ public class RadioManager {
            ModuleProperties other = (ModuleProperties) obj;
            if (mId != other.getId())
                return false;
            if (!TextUtils.equals(mServiceName, other.mServiceName)) return false;
            if (mClassId != other.getClassId())
                return false;
            if (mImplementor == null) {
@@ -1457,7 +1476,35 @@ public class RadioManager {
     *  <li>{@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails, </li>
     * </ul>
     */
    public native int listModules(List <ModuleProperties> modules);
    public int listModules(List<ModuleProperties> modules) {
        if (modules == null) {
            Log.e(TAG, "the output list must not be empty");
            return STATUS_BAD_VALUE;
        }

        if (mService == null) {
            return nativeListModules(modules);
        }

        Log.v(TAG, "Listing available tuners...");
        List<ModuleProperties> returnedList;
        try {
            returnedList = mService.listModules();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed listing available tuners", e);
            return STATUS_DEAD_OBJECT;
        }

        if (returnedList == null) {
            Log.e(TAG, "Returned list was a null");
            return STATUS_ERROR;
        }

        modules.addAll(returnedList);
        return STATUS_OK;
    }

    private native int nativeListModules(List<ModuleProperties> modules);

    /**
     * Open an interface to control a tuner on a given broadcast radio module.
@@ -1487,7 +1534,8 @@ public class RadioManager {
            try {
                tuner = mService.openTuner(moduleId, config, withAudio, halCallback);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
                Log.e(TAG, "Failed to open tuner", e);
                return null;
            }
            if (tuner == null) {
                Log.e(TAG, "Failed to open tuner");
+5 −3
Original line number Diff line number Diff line
@@ -449,7 +449,7 @@ android_hardware_Radio_listModules(JNIEnv *env, jobject clazz,
        bool isBgscanSupported = false;  // TODO(b/32621193): pass from the HAL
        jstring jVendorExension = env->NewStringUTF("");  // TODO(b/32621193): pass from the HAL
        jobject jModule = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
                                               nModules[i].handle, nModules[i].class_id,
                                               nModules[i].handle, nullptr, nModules[i].class_id,
                                               jImplementor, jProduct, jVersion, jSerial,
                                               nModules[i].num_tuners,
                                               nModules[i].num_audio_sources,
@@ -819,7 +819,7 @@ android_hardware_Radio_hasControl(JNIEnv *env, jobject thiz)


static JNINativeMethod gMethods[] = {
    {"listModules",
    {"nativeListModules",
        "(Ljava/util/List;)I",
        (void *)android_hardware_Radio_listModules},
};
@@ -888,7 +888,9 @@ int register_android_hardware_Radio(JNIEnv *env)
    jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName);
    gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass);
    gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>",
            "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIZ[Landroid/hardware/radio/RadioManager$BandDescriptor;ZLjava/lang/String;)V");
            "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;"
            "Ljava/lang/String;IIZ[Landroid/hardware/radio/RadioManager$BandDescriptor;Z"
            "Ljava/lang/String;)V");

    jclass bandDescriptorClass = FindClassOrDie(env, kRadioBandDescriptorClassPathName);
    gRadioBandDescriptorClass = MakeGlobalRefOrDie(env, bandDescriptorClass);
+20 −0
Original line number Diff line number Diff line
@@ -21,10 +21,13 @@ import android.hardware.radio.IRadioService;
import android.hardware.radio.ITuner;
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
import android.os.ParcelableException;
import android.util.Slog;

import com.android.server.SystemService;

import java.util.List;

public class RadioService extends SystemService {
    // TODO(b/36863239): rename to RadioService when native service goes away
    private static final String TAG = "RadioServiceJava";
@@ -37,6 +40,7 @@ public class RadioService extends SystemService {
    private final long mNativeContext = nativeInit();

    private final Object mLock = new Object();
    private List<RadioManager.ModuleProperties> mModules = null;

    public RadioService(Context context) {
        super(context);
@@ -50,6 +54,7 @@ public class RadioService extends SystemService {

    private native long nativeInit();
    private native void nativeFinalize(long nativeContext);
    private native List<RadioManager.ModuleProperties> nativeLoadModules(long nativeContext);
    private native Tuner nativeOpenTuner(long nativeContext, int moduleId,
            RadioManager.BandConfig config, boolean withAudio, ITunerCallback callback);

@@ -60,6 +65,21 @@ public class RadioService extends SystemService {
    }

    private class RadioServiceImpl extends IRadioService.Stub {
        @Override
        public List<RadioManager.ModuleProperties> listModules() {
            synchronized (mLock) {
                if (mModules != null) return mModules;

                mModules = nativeLoadModules(mNativeContext);
                if (mModules == null) {
                    throw new ParcelableException(new NullPointerException(
                            "couldn't load radio modules"));
                }

                return mModules;
            }
        }

        @Override
        public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
                boolean withAudio, ITunerCallback callback) {
Loading