OSDN Git Service

Make it possible to check if a given program/identifier type is supported.
authorTomasz Wasilczyk <twasilczyk@google.com>
Sun, 16 Jul 2017 22:15:40 +0000 (15:15 -0700)
committerTomasz Wasilczyk <twasilczyk@google.com>
Mon, 17 Jul 2017 23:28:18 +0000 (16:28 -0700)
Test: instrumentalization
Bug: b/63702941
Change-Id: I436b62fa4cda8458a92a15a75543bedd43e65dcd

api/system-current.txt
core/java/android/hardware/radio/RadioManager.java
services/core/jni/com_android_server_radio_convert.cpp

index 28e4c48..5c9f986 100644 (file)
@@ -17383,6 +17383,8 @@ package android.hardware.radio {
     method public java.lang.String getVersion();
     method public boolean isBackgroundScanningSupported();
     method public boolean isCaptureSupported();
+    method public boolean isProgramIdentifierSupported(int);
+    method public boolean isProgramTypeSupported(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.radio.RadioManager.ModuleProperties> CREATOR;
   }
index 3a0306e..6a59be0 100644 (file)
@@ -34,6 +34,8 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * The RadioManager class allows to control a broadcast radio tuner present on the device.
@@ -132,11 +134,15 @@ public class RadioManager {
         private final boolean mIsCaptureSupported;
         private final BandDescriptor[] mBands;
         private final boolean mIsBgScanSupported;
+        private final Set<Integer> mSupportedProgramTypes;
+        private final Set<Integer> mSupportedIdentifierTypes;
         private final String mVendorExension;
 
         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,
+                @ProgramSelector.ProgramType int[] supportedProgramTypes,
+                @ProgramSelector.IdentifierType int[] supportedIdentifierTypes,
                 String vendorExension) {
             mId = id;
             mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName;
@@ -150,9 +156,18 @@ public class RadioManager {
             mIsCaptureSupported = isCaptureSupported;
             mBands = bands;
             mIsBgScanSupported = isBgScanSupported;
+            mSupportedProgramTypes = arrayToSet(supportedProgramTypes);
+            mSupportedIdentifierTypes = arrayToSet(supportedIdentifierTypes);
             mVendorExension = vendorExension;
         }
 
+        private static Set<Integer> arrayToSet(int[] arr) {
+            return Arrays.stream(arr).boxed().collect(Collectors.toSet());
+        }
+
+        private static int[] setToArray(Set<Integer> set) {
+            return set.stream().mapToInt(Integer::intValue).toArray();
+        }
 
         /** Unique module identifier provided by the native service.
          * For use with {@link #openTuner(int, BandConfig, boolean, Callback, Handler)}.
@@ -245,6 +260,31 @@ public class RadioManager {
         }
 
         /**
+         * Checks, if a given program type is supported by this tuner.
+         *
+         * If a program type is supported by radio module, it means it can tune
+         * to ProgramSelector of a given type.
+         *
+         * @return {@code true} if a given program type is supported.
+         */
+        public boolean isProgramTypeSupported(@ProgramSelector.ProgramType int type) {
+            return mSupportedProgramTypes.contains(type);
+        }
+
+        /**
+         * Checks, if a given program identifier is supported by this tuner.
+         *
+         * If an identifier is supported by radio module, it means it can use it for
+         * tuning to ProgramSelector with either primary or secondary Identifier of
+         * a given type.
+         *
+         * @return {@code true} if a given program type is supported.
+         */
+        public boolean isProgramIdentifierSupported(@ProgramSelector.IdentifierType int type) {
+            return mSupportedIdentifierTypes.contains(type);
+        }
+
+        /**
          * Opaque vendor-specific string, passed from HAL without changes.
          * Format of this string can vary across vendors.
          *
@@ -283,6 +323,8 @@ public class RadioManager {
                 mBands[i] = (BandDescriptor) tmp[i];
             }
             mIsBgScanSupported = in.readInt() == 1;
+            mSupportedProgramTypes = arrayToSet(in.createIntArray());
+            mSupportedIdentifierTypes = arrayToSet(in.createIntArray());
             mVendorExension = in.readString();
         }
 
@@ -311,6 +353,8 @@ public class RadioManager {
             dest.writeInt(mIsCaptureSupported ? 1 : 0);
             dest.writeParcelableArray(mBands, flags);
             dest.writeInt(mIsBgScanSupported ? 1 : 0);
+            dest.writeIntArray(setToArray(mSupportedProgramTypes));
+            dest.writeIntArray(setToArray(mSupportedIdentifierTypes));
             dest.writeString(mVendorExension);
         }
 
index af000bd..6cad7f8 100644 (file)
@@ -185,6 +185,44 @@ void ThrowParcelableRuntimeException(JNIEnv *env, const std::string& msg) {
     ALOGE_IF(res != JNI_OK, "Couldn't throw parcelable runtime exception");
 }
 
+static JavaRef<jintArray> ArrayFromHal(JNIEnv *env, const hidl_vec<uint32_t>& vec) {
+    auto jArr = make_javaref(env, env->NewIntArray(vec.size()));
+    auto jArrElements = env->GetIntArrayElements(jArr.get(), nullptr);
+    for (size_t i = 0; i < vec.size(); i++) {
+        jArrElements[i] = vec[i];
+    }
+    env->ReleaseIntArrayElements(jArr.get(), jArrElements, 0);
+    return jArr;
+}
+
+static JavaRef<jlongArray> ArrayFromHal(JNIEnv *env, const hidl_vec<uint64_t>& vec) {
+    auto jArr = make_javaref(env, env->NewLongArray(vec.size()));
+    auto jArrElements = env->GetLongArrayElements(jArr.get(), nullptr);
+    for (size_t i = 0; i < vec.size(); i++) {
+        jArrElements[i] = vec[i];
+    }
+    env->ReleaseLongArrayElements(jArr.get(), jArrElements, 0);
+    return jArr;
+}
+
+template <typename T>
+static JavaRef<jobjectArray> ArrayFromHal(JNIEnv *env, const hidl_vec<T>& vec,
+        jclass jElementClass, std::function<JavaRef<jobject>(JNIEnv*, const T&)> converter) {
+    auto jArr = make_javaref(env, env->NewObjectArray(vec.size(), jElementClass, nullptr));
+    for (size_t i = 0; i < vec.size(); i++) {
+        auto jElement = converter(env, vec[i]);
+        env->SetObjectArrayElement(jArr.get(), i, jElement.get());
+    }
+    return jArr;
+}
+
+template <typename T>
+static JavaRef<jobjectArray> ArrayFromHal(JNIEnv *env, const hidl_vec<T>& vec,
+        jclass jElementClass, JavaRef<jobject>(*converter)(JNIEnv*, const T&)) {
+    return ArrayFromHal(env, vec, jElementClass,
+            std::function<JavaRef<jobject>(JNIEnv*, const T&)>(converter));
+}
+
 static Rds RdsForRegion(bool rds, Region region) {
     if (!rds) return Rds::NONE;
 
@@ -220,6 +258,7 @@ static Deemphasis DeemphasisForRegion(Region region) {
 static JavaRef<jobject> ModulePropertiesFromHal(JNIEnv *env, const V1_0::Properties &prop10,
         const V1_1::Properties *prop11, jint moduleId, const std::string& serviceName) {
     ALOGV("ModulePropertiesFromHal()");
+    using namespace std::placeholders;
 
     auto jServiceName = make_javastr(env, serviceName);
     auto jImplementor = make_javastr(env, prop10.implementor);
@@ -228,21 +267,19 @@ static JavaRef<jobject> ModulePropertiesFromHal(JNIEnv *env, const V1_0::Propert
     auto jSerial = make_javastr(env, prop10.serial);
     bool isBgScanSupported = prop11 ? prop11->supportsBackgroundScanning : false;
     auto jVendorExtension = prop11 ? make_javastr(env, prop11->vendorExension) : nullptr;
-
-    auto jBands = make_javaref(env, env->NewObjectArray(prop10.bands.size(),
-            gjni.BandDescriptor.clazz, nullptr));
-    int i = 0;
-    for (auto &&band : prop10.bands) {
-        // ITU_1 is the default region just because its index is 0.
-        auto jBand = BandDescriptorFromHal(env, band, Region::ITU_1);
-        env->SetObjectArrayElement(jBands.get(), i++, jBand.get());
-    }
+    // ITU_1 is the default region just because its index is 0.
+    auto jBands = ArrayFromHal<V1_0::BandConfig>(env, prop10.bands, gjni.BandDescriptor.clazz,
+        std::bind(BandDescriptorFromHal, _1, _2, Region::ITU_1));
+    auto jSupportedProgramTypes =
+            prop11 ? ArrayFromHal(env, prop11->supportedProgramTypes) : nullptr;
+    auto jSupportedIdentifierTypes =
+            prop11 ? ArrayFromHal(env, prop11->supportedIdentifierTypes) : nullptr;
 
     return make_javaref(env, env->NewObject(gjni.ModuleProperties.clazz,
             gjni.ModuleProperties.cstor, moduleId, jServiceName.get(), prop10.classId,
             jImplementor.get(), jProduct.get(), jVersion.get(), jSerial.get(), prop10.numTuners,
             prop10.numAudioSources, prop10.supportsCapture, jBands.get(), isBgScanSupported,
-            jVendorExtension.get()));
+            jSupportedProgramTypes.get(), jSupportedIdentifierTypes.get(), jVendorExtension.get()));
 }
 
 JavaRef<jobject> ModulePropertiesFromHal(JNIEnv *env, const V1_0::Properties &properties,
@@ -411,20 +448,9 @@ static JavaRef<jobject> ProgramIdentifierFromHal(JNIEnv *env, const ProgramIdent
 static JavaRef<jobject> ProgramSelectorFromHal(JNIEnv *env, const ProgramSelector &selector) {
     ALOGV("ProgramSelectorFromHal()");
     auto jPrimary = ProgramIdentifierFromHal(env, selector.primaryId);
-
-    auto jSecondary = make_javaref(env, env->NewObjectArray(selector.secondaryIds.size(),
-            gjni.ProgramSelector.Identifier.clazz, nullptr));
-    for (size_t i = 0; i < selector.secondaryIds.size(); i++) {
-        auto jId = ProgramIdentifierFromHal(env, selector.secondaryIds[i]);
-        env->SetObjectArrayElement(jSecondary.get(), i, jId.get());
-    }
-
-    auto jVendor = make_javaref(env, env->NewLongArray(selector.vendorIds.size()));
-    auto jVendorElements = env->GetLongArrayElements(jVendor.get(), nullptr);
-    for (size_t i = 0; i < selector.vendorIds.size(); i++) {
-        jVendorElements[i] = selector.vendorIds[i];
-    }
-    env->ReleaseLongArrayElements(jVendor.get(), jVendorElements, 0);
+    auto jSecondary = ArrayFromHal(env, selector.secondaryIds,
+            gjni.ProgramSelector.Identifier.clazz, ProgramIdentifierFromHal);
+    auto jVendor = ArrayFromHal(env, selector.vendorIds);
 
     return make_javaref(env, env->NewObject(gjni.ProgramSelector.clazz, gjni.ProgramSelector.cstor,
             selector.programType, jPrimary.get(), jSecondary.get(), jVendor.get()));
@@ -554,7 +580,7 @@ void register_android_server_radio_convert(JNIEnv *env) {
     gjni.ModuleProperties.cstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>",
             "(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");
+            "[I[ILjava/lang/String;)V");
 
     auto programInfoClass = FindClassOrDie(env, "android/hardware/radio/RadioManager$ProgramInfo");
     gjni.ProgramInfo.clazz = MakeGlobalRefOrDie(env, programInfoClass);