Merge "Fix RescueParty querying DeviceConfig before SettingsProvider ready" into rvc-dev
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 054e5e0..91a8572 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -186,6 +186,7 @@
import android.telephony.TelephonyRegistryManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Slog;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.WindowManager;
@@ -222,6 +223,9 @@
public final class SystemServiceRegistry {
private static final String TAG = "SystemServiceRegistry";
+ /** @hide */
+ public static boolean sEnableServiceNotFoundWtf = false;
+
// Service registry information.
// This information is never changed once static initialization has completed.
private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
@@ -1364,8 +1368,30 @@
* @hide
*/
public static Object getSystemService(ContextImpl ctx, String name) {
- ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
- return fetcher != null ? fetcher.getService(ctx) : null;
+ if (name == null) {
+ return null;
+ }
+ final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
+ if (fetcher == null) {
+ if (sEnableServiceNotFoundWtf) {
+ Slog.wtf(TAG, "Unknown manager requested: " + name);
+ }
+ return null;
+ }
+
+ final Object ret = fetcher.getService(ctx);
+ if (sEnableServiceNotFoundWtf && ret == null) {
+ // Some services do return null in certain situations, so don't do WTF for them.
+ switch (name) {
+ case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
+ case Context.APP_PREDICTION_SERVICE:
+ case Context.INCREMENTAL_SERVICE:
+ return null;
+ }
+ Slog.wtf(TAG, "Manager wrapper not available: " + name);
+ return null;
+ }
+ return ret;
}
/**
@@ -1373,7 +1399,15 @@
* @hide
*/
public static String getSystemServiceName(Class<?> serviceClass) {
- return SYSTEM_SERVICE_NAMES.get(serviceClass);
+ if (serviceClass == null) {
+ return null;
+ }
+ final String serviceName = SYSTEM_SERVICE_NAMES.get(serviceClass);
+ if (sEnableServiceNotFoundWtf && serviceName == null) {
+ // This should be a caller bug.
+ Slog.wtf(TAG, "Unknown manager requested: " + serviceClass.getCanonicalName());
+ }
+ return serviceName;
}
/**
@@ -1683,7 +1717,9 @@
try {
cache.wait();
} catch (InterruptedException e) {
- Log.w(TAG, "getService() interrupted");
+ // This shouldn't normally happen, but if someone interrupts the
+ // thread, it will.
+ Slog.wtf(TAG, "getService() interrupted");
Thread.currentThread().interrupt();
return null;
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index d4494acb7e..cf1f1b5 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -602,6 +602,9 @@
*/
@Nullable
public FrontendStatus getFrontendStatus(@NonNull @FrontendStatusType int[] statusTypes) {
+ if (mFrontend == null) {
+ throw new IllegalStateException("frontend is not initialized");
+ }
return nativeGetFrontendStatus(statusTypes);
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4a7e8e1..312e5fe 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -124,7 +124,11 @@
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
+using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_0::ITuner;
using ::android::hardware::tv::tuner::V1_0::LnbPosition;
@@ -1453,6 +1457,254 @@
numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter);
}
+jobject JTuner::getFrontendStatus(jintArray types) {
+ if (mFe == NULL) {
+ return NULL;
+ }
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jsize size = env->GetArrayLength(types);
+ std::vector<FrontendStatusType> v(size);
+ env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
+
+ Result res;
+ hidl_vec<FrontendStatus> status;
+ mFe->getStatus(v,
+ [&](Result r, const hidl_vec<FrontendStatus>& s) {
+ res = r;
+ status = s;
+ });
+ if (res != Result::SUCCESS) {
+ return NULL;
+ }
+
+ jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
+ jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
+ jobject statusObj = env->NewObject(clazz, init);
+
+ jclass intClazz = env->FindClass("java/lang/Integer");
+ jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V");
+ jclass booleanClazz = env->FindClass("java/lang/Boolean");
+ jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V");
+
+ for (auto s : status) {
+ switch(s.getDiscriminator()) {
+ case FrontendStatus::hidl_discriminator::isDemodLocked: {
+ jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;");
+ jobject newBooleanObj = env->NewObject(
+ booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked()));
+ env->SetObjectField(statusObj, field, newBooleanObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::snr: {
+ jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.snr()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::ber: {
+ jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.ber()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::per: {
+ jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.per()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::preBer: {
+ jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.preBer()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::signalQuality: {
+ jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.signalQuality()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::signalStrength: {
+ jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.signalStrength()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::symbolRate: {
+ jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.symbolRate()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::innerFec: {
+ jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;");
+ jclass longClazz = env->FindClass("java/lang/Long");
+ jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V");
+ jobject newLongObj = env->NewObject(
+ longClazz, initLong, static_cast<jlong>(s.innerFec()));
+ env->SetObjectField(statusObj, field, newLongObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::modulation: {
+ jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;");
+ FrontendModulationStatus modulation = s.modulation();
+ jint intModulation;
+ bool valid = true;
+ switch(modulation.getDiscriminator()) {
+ case FrontendModulationStatus::hidl_discriminator::dvbc: {
+ intModulation = static_cast<jint>(modulation.dvbc());
+ break;
+ }
+ case FrontendModulationStatus::hidl_discriminator::dvbs: {
+ intModulation = static_cast<jint>(modulation.dvbs());
+ break;
+ }
+ case FrontendModulationStatus::hidl_discriminator::isdbs: {
+ intModulation = static_cast<jint>(modulation.isdbs());
+ break;
+ }
+ case FrontendModulationStatus::hidl_discriminator::isdbs3: {
+ intModulation = static_cast<jint>(modulation.isdbs3());
+ break;
+ }
+ case FrontendModulationStatus::hidl_discriminator::isdbt: {
+ intModulation = static_cast<jint>(modulation.isdbt());
+ break;
+ }
+ default: {
+ valid = false;
+ break;
+ }
+ }
+ if (valid) {
+ jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation);
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ }
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::inversion: {
+ jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.inversion()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::lnbVoltage: {
+ jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.lnbVoltage()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::plpId: {
+ jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.plpId()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::isEWBS: {
+ jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;");
+ jobject newBooleanObj = env->NewObject(
+ booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS()));
+ env->SetObjectField(statusObj, field, newBooleanObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::agc: {
+ jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.agc()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::isLnaOn: {
+ jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;");
+ jobject newBooleanObj = env->NewObject(
+ booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn()));
+ env->SetObjectField(statusObj, field, newBooleanObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::isLayerError: {
+ jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z");
+ hidl_vec<bool> layerErr = s.isLayerError();
+
+ jbooleanArray valObj = env->NewBooleanArray(layerErr.size());
+
+ for (size_t i = 0; i < layerErr.size(); i++) {
+ jboolean x = layerErr[i];
+ env->SetBooleanArrayRegion(valObj, i, 1, &x);
+ }
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::mer: {
+ jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.mer()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::freqOffset: {
+ jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.freqOffset()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::hierarchy: {
+ jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.hierarchy()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::isRfLocked: {
+ jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;");
+ jobject newBooleanObj = env->NewObject(
+ booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked()));
+ env->SetObjectField(statusObj, field, newBooleanObj);
+ break;
+ }
+ case FrontendStatus::hidl_discriminator::plpInfo: {
+ jfieldID field = env->GetFieldID(clazz, "mPlpInfo",
+ "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;");
+ jclass plpClazz = env->FindClass(
+ "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo");
+ jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V");
+
+ hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo();
+
+ jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
+ for (int i = 0; i < plpInfos.size(); i++) {
+ auto info = plpInfos[i];
+ jint plpId = (jint) info.plpId;
+ jboolean isLocked = (jboolean) info.isLocked;
+ jint uec = (jint) info.uec;
+
+ jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec);
+ env->SetObjectArrayElement(valObj, i, plpObj);
+ }
+
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ return statusObj;
+}
+
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -2086,8 +2338,10 @@
return tuner->setLna(enable);
}
-static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
- return NULL;
+static jobject android_media_tv_Tuner_get_frontend_status(
+ JNIEnv* env, jobject thiz, jintArray types) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->getFrontendStatus(types);
}
static jobject android_media_tv_Tuner_get_av_sync_hw_id(
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 7e860b9..e6f10b2 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -187,6 +187,7 @@
jobject openDescrambler();
jobject openDvr(DvrType type, jlong bufferSize);
jobject getDemuxCaps();
+ jobject getFrontendStatus(jintArray types);
protected:
Result openDemux();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1939313..2a914ec 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -30,6 +30,7 @@
import android.app.ActivityThread;
import android.app.AppCompatCallbacks;
import android.app.INotificationManager;
+import android.app.SystemServiceRegistry;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ContentResolver;
import android.content.Context;
@@ -513,6 +514,8 @@
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
+ SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
+
// Initialize native services.
System.loadLibrary("android_servers");