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

Commit b4d37e53 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk Committed by Android (Google) Code Review
Browse files

Merge changes from topic 'radio-service'

* changes:
  Add permission check for java RadioService.
  Implement listing broadcast radio modules.
parents d6cc828e 32d26a37
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);
+31 −0
Original line number Diff line number Diff line
@@ -16,15 +16,20 @@

package com.android.server.radio;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
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 +42,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 +56,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,9 +67,33 @@ public class RadioService extends SystemService {
    }

    private class RadioServiceImpl extends IRadioService.Stub {
        private void enforcePolicyAccess() {
            if (PackageManager.PERMISSION_GRANTED != getContext().checkCallingPermission(
                    Manifest.permission.ACCESS_FM_RADIO)) {
                throw new SecurityException("ACCESS_FM_RADIO permission not granted");
            }
        }

        @Override
        public List<RadioManager.ModuleProperties> listModules() {
            enforcePolicyAccess();
            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) {
            enforcePolicyAccess();
            if (callback == null) {
                throw new IllegalArgumentException("Callback must not be empty");
            }
Loading