summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt5
-rw-r--r--core/jni/OWNERS6
-rw-r--r--media/java/android/media/tv/ITvInputManager.aidl2
-rwxr-xr-xmedia/java/android/media/tv/ITvInputService.aidl23
-rw-r--r--media/java/android/media/tv/TvInputManager.java51
-rwxr-xr-xmedia/java/android/media/tv/TvInputService.java76
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/com/android/server/ConsumerIrService.java60
-rwxr-xr-xservices/core/java/com/android/server/tv/TvInputManagerService.java86
-rw-r--r--services/core/jni/com_android_server_ConsumerIrService.cpp8
10 files changed, 294 insertions, 24 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index bb454a642ff1..09c58ae51abf 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5841,9 +5841,11 @@ package android.media.tv {
method @Nullable @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, @NonNull android.media.tv.TvInputInfo, @Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.TvInputManager.HardwareCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
+ method @NonNull public java.util.List<java.lang.String> getAvailableExtensionInterfaceNames(@NonNull String);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO) public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
+ method @Nullable public android.os.IBinder getExtensionInterface(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean isSingleSessionActive();
@@ -5874,6 +5876,9 @@ package android.media.tv {
public abstract class TvInputService extends android.app.Service {
method @Nullable public android.os.IBinder createExtension();
+ method @NonNull public java.util.List<java.lang.String> getAvailableExtensionInterfaceNames();
+ method @Nullable public android.os.IBinder getExtensionInterface(@NonNull String);
+ method @Nullable public String getExtensionInterfacePermission(@NonNull String);
method @Nullable public android.media.tv.TvInputInfo onHardwareAdded(android.media.tv.TvInputHardwareInfo);
method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
method @Nullable public android.media.tv.TvInputInfo onHdmiDeviceAdded(android.hardware.hdmi.HdmiDeviceInfo);
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 790c39e73bff..832c49801bdc 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -55,13 +55,17 @@ per-file android_media_* = file:/media/java/android/media/OWNERS
per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS
per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS
per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
-per-file android_se_* = file:/core/java/android/se/OWNERS
+per-file android_se_* = file:/omapi/java/android/se/OWNERS
per-file android_security_* = file:/core/java/android/security/OWNERS
per-file android_view_* = file:/core/java/android/view/OWNERS
per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS
### Graphics ###
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
+
+### Text ###
+per-file android_text_* = file:/core/java/android/text/OWNERS
+
# These are highly common-use files
per-file Android.bp = file:/graphics/java/android/graphics/OWNERS
per-file AndroidRuntime.cpp = file:/graphics/java/android/graphics/OWNERS
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index d8d1ba1341bb..a0827acbaf4f 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -45,6 +45,8 @@ interface ITvInputManager {
TvInputInfo getTvInputInfo(in String inputId, int userId);
void updateTvInputInfo(in TvInputInfo inputInfo, int userId);
int getTvInputState(in String inputId, int userId);
+ List<String> getAvailableExtensionInterfaceNames(in String inputId, int userId);
+ IBinder getExtensionInterface(in String inputId, in String name, int userId);
List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId);
diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
index 8ccf13ae2d72..64a23a2323f6 100755
--- a/media/java/android/media/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -26,18 +26,21 @@ import android.view.InputChannel;
* Top-level interface to a TV input component (implemented in a Service).
* @hide
*/
-oneway interface ITvInputService {
- void registerCallback(in ITvInputServiceCallback callback);
- void unregisterCallback(in ITvInputServiceCallback callback);
- void createSession(in InputChannel channel, in ITvInputSessionCallback callback,
+interface ITvInputService {
+ oneway void registerCallback(in ITvInputServiceCallback callback);
+ oneway void unregisterCallback(in ITvInputServiceCallback callback);
+ oneway void createSession(in InputChannel channel, in ITvInputSessionCallback callback,
in String inputId, in String sessionId);
- void createRecordingSession(in ITvInputSessionCallback callback, in String inputId,
+ oneway void createRecordingSession(in ITvInputSessionCallback callback, in String inputId,
in String sessionId);
+ List<String> getAvailableExtensionInterfaceNames();
+ IBinder getExtensionInterface(in String name);
+ String getExtensionInterfacePermission(in String name);
// For hardware TvInputService
- void notifyHardwareAdded(in TvInputHardwareInfo hardwareInfo);
- void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
- void notifyHdmiDeviceAdded(in HdmiDeviceInfo deviceInfo);
- void notifyHdmiDeviceRemoved(in HdmiDeviceInfo deviceInfo);
- void notifyHdmiDeviceUpdated(in HdmiDeviceInfo deviceInfo);
+ oneway void notifyHardwareAdded(in TvInputHardwareInfo hardwareInfo);
+ oneway void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
+ oneway void notifyHdmiDeviceAdded(in HdmiDeviceInfo deviceInfo);
+ oneway void notifyHdmiDeviceRemoved(in HdmiDeviceInfo deviceInfo);
+ oneway void notifyHdmiDeviceUpdated(in HdmiDeviceInfo deviceInfo);
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 34e4609a71f7..efd9d1005b05 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1390,6 +1390,57 @@ public final class TvInputManager {
}
/**
+ * Returns available extension interfaces of a given hardware TV input. This can be used to
+ * provide domain-specific features that are only known between certain hardware TV inputs
+ * and their clients.
+ *
+ * @param inputId The ID of the TV input.
+ * @return a non-null list of extension interface names available to the caller. An empty
+ * list indicates the given TV input is not found, or the given TV input is not a
+ * hardware TV input, or the given TV input doesn't support any extension
+ * interfaces, or the caller doesn't hold the required permission for the extension
+ * interfaces supported by the given TV input.
+ * @see #getExtensionInterface
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public List<String> getAvailableExtensionInterfaceNames(@NonNull String inputId) {
+ Preconditions.checkNotNull(inputId);
+ try {
+ return mService.getAvailableExtensionInterfaceNames(inputId, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns an extension interface of a given hardware TV input. This can be used to provide
+ * domain-specific features that are only known between certain hardware TV inputs and
+ * their clients.
+ *
+ * @param inputId The ID of the TV input.
+ * @param name The extension interface name.
+ * @return an {@link IBinder} for the given extension interface, {@code null} if the given TV
+ * input is not found, or if the given TV input is not a hardware TV input, or if the
+ * given TV input doesn't support the given extension interface, or if the caller
+ * doesn't hold the required permission for the given extension interface.
+ * @see #getAvailableExtensionInterfaceNames
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public IBinder getExtensionInterface(@NonNull String inputId, @NonNull String name) {
+ Preconditions.checkNotNull(inputId);
+ Preconditions.checkNotNull(name);
+ try {
+ return mService.getExtensionInterface(inputId, name, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Registers a {@link TvInputCallback}.
*
* @param callback A callback used to monitor status of the TV inputs.
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 77fb2b236698..4a429fb551d7 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -201,6 +201,21 @@ public abstract class TvInputService extends Service {
}
@Override
+ public List<String> getAvailableExtensionInterfaceNames() {
+ return TvInputService.this.getAvailableExtensionInterfaceNames();
+ }
+
+ @Override
+ public IBinder getExtensionInterface(String name) {
+ return TvInputService.this.getExtensionInterface(name);
+ }
+
+ @Override
+ public String getExtensionInterfacePermission(String name) {
+ return TvInputService.this.getExtensionInterfacePermission(name);
+ }
+
+ @Override
public void notifyHardwareAdded(TvInputHardwareInfo hardwareInfo) {
mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HARDWARE_INPUT,
hardwareInfo).sendToTarget();
@@ -253,6 +268,67 @@ public abstract class TvInputService extends Service {
}
/**
+ * Returns available extension interfaces. This can be used to provide domain-specific
+ * features that are only known between certain hardware TV inputs and their clients.
+ *
+ * <p>Note that this service-level extension interface mechanism is only for hardware
+ * TV inputs that are bound even when sessions are not created.
+ *
+ * @return a non-null list of available extension interface names. An empty list
+ * indicates the TV input doesn't support any extension interfaces.
+ * @see #getExtensionInterface
+ * @see #getExtensionInterfacePermission
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public List<String> getAvailableExtensionInterfaceNames() {
+ return new ArrayList<>();
+ }
+
+ /**
+ * Returns an extension interface. This can be used to provide domain-specific features
+ * that are only known between certain hardware TV inputs and their clients.
+ *
+ * <p>Note that this service-level extension interface mechanism is only for hardware
+ * TV inputs that are bound even when sessions are not created.
+ *
+ * @param name The extension interface name.
+ * @return an {@link IBinder} for the given extension interface, {@code null} if the TV input
+ * doesn't support the given extension interface.
+ * @see #getAvailableExtensionInterfaceNames
+ * @see #getExtensionInterfacePermission
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public IBinder getExtensionInterface(@NonNull String name) {
+ return null;
+ }
+
+ /**
+ * Returns a permission for the given extension interface. This can be used to provide
+ * domain-specific features that are only known between certain hardware TV inputs and their
+ * clients.
+ *
+ * <p>Note that this service-level extension interface mechanism is only for hardware
+ * TV inputs that are bound even when sessions are not created.
+ *
+ * @param name The extension interface name.
+ * @return a name of the permission being checked for the given extension interface,
+ * {@code null} if there is no required permission, or if the TV input doesn't
+ * support the given extension interface.
+ * @see #getAvailableExtensionInterfaceNames
+ * @see #getExtensionInterface
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public String getExtensionInterfacePermission(@NonNull String name) {
+ return null;
+ }
+
+ /**
* Returns a concrete implementation of {@link Session}.
*
* <p>May return {@code null} if this TV input service fails to create a session for some
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 1dda14ca0db5..7a4f1de95e0c 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -154,6 +154,7 @@ java_library_static {
"android.hardware.oemlock-V1.0-java",
"android.hardware.configstore-V1.1-java",
"android.hardware.contexthub-V1.0-java",
+ "android.hardware.ir-V1-java",
"android.hardware.rebootescrow-V1-java",
"android.hardware.soundtrigger-V2.3-java",
"android.hardware.power.stats-V1-java",
diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java
index 2ed6c77baa0d..c4e84a4cd138 100644
--- a/services/core/java/com/android/server/ConsumerIrService.java
+++ b/services/core/java/com/android/server/ConsumerIrService.java
@@ -19,17 +19,19 @@ package com.android.server;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.IConsumerIrService;
+import android.hardware.ir.ConsumerIrFreqRange;
+import android.hardware.ir.IConsumerIr;
import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Slog;
-import java.lang.RuntimeException;
-
public class ConsumerIrService extends IConsumerIrService.Stub {
private static final String TAG = "ConsumerIrService";
private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
- private static native boolean halOpen();
+ private static native boolean getHidlHalService();
private static native int halTransmit(int carrierFrequency, int[] pattern);
private static native int[] halGetCarrierFrequencies();
@@ -37,6 +39,7 @@ public class ConsumerIrService extends IConsumerIrService.Stub {
private final PowerManager.WakeLock mWakeLock;
private final boolean mHasNativeHal;
private final Object mHalLock = new Object();
+ private IConsumerIr mAidlService = null;
ConsumerIrService(Context context) {
mContext = context;
@@ -45,7 +48,8 @@ public class ConsumerIrService extends IConsumerIrService.Stub {
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(true);
- mHasNativeHal = halOpen();
+ mHasNativeHal = getHalService();
+
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
if (!mHasNativeHal) {
throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
@@ -60,6 +64,19 @@ public class ConsumerIrService extends IConsumerIrService.Stub {
return mHasNativeHal;
}
+ private boolean getHalService() {
+ // Attempt to get the AIDL HAL service first
+ final String fqName = IConsumerIr.DESCRIPTOR + "/default";
+ mAidlService = IConsumerIr.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(fqName));
+ if (mAidlService != null) {
+ return true;
+ }
+
+ // Fall back to the HIDL HAL service
+ return getHidlHalService();
+ }
+
private void throwIfNoIrEmitter() {
if (!mHasNativeHal) {
throw new UnsupportedOperationException("IR emitter not available");
@@ -91,10 +108,18 @@ public class ConsumerIrService extends IConsumerIrService.Stub {
// Right now there is no mechanism to ensure fair queing of IR requests
synchronized (mHalLock) {
- int err = halTransmit(carrierFrequency, pattern);
-
- if (err < 0) {
- Slog.e(TAG, "Error transmitting: " + err);
+ if (mAidlService != null) {
+ try {
+ mAidlService.transmit(carrierFrequency, pattern);
+ } catch (RemoteException ignore) {
+ Slog.e(TAG, "Error transmitting frequency: " + carrierFrequency);
+ }
+ } else {
+ int err = halTransmit(carrierFrequency, pattern);
+
+ if (err < 0) {
+ Slog.e(TAG, "Error transmitting: " + err);
+ }
}
}
}
@@ -109,7 +134,24 @@ public class ConsumerIrService extends IConsumerIrService.Stub {
throwIfNoIrEmitter();
synchronized(mHalLock) {
- return halGetCarrierFrequencies();
+ if (mAidlService != null) {
+ try {
+ ConsumerIrFreqRange[] output = mAidlService.getCarrierFreqs();
+ if (output.length <= 0) {
+ Slog.e(TAG, "Error getting carrier frequencies.");
+ }
+ int[] result = new int[output.length * 2];
+ for (int i = 0; i < output.length; i++) {
+ result[i * 2] = output[i].minHz;
+ result[i * 2 + 1] = output[i].maxHz;
+ }
+ return result;
+ } catch (RemoteException ignore) {
+ return null;
+ }
+ } else {
+ return halGetCarrierFrequencies();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 2f54f302af6c..cb3d00a20f65 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -89,6 +89,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
@@ -1173,6 +1174,91 @@ public final class TvInputManagerService extends SystemService {
}
@Override
+ public List<String> getAvailableExtensionInterfaceNames(String inputId, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid,
+ userId, "getAvailableExtensionInterfaceNames");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ITvInputService service = null;
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+ TvInputState inputState = userState.inputMap.get(inputId);
+ if (inputState != null) {
+ ServiceState serviceState =
+ userState.serviceStateMap.get(inputState.info.getComponent());
+ if (serviceState != null && serviceState.isHardware
+ && serviceState.service != null) {
+ service = serviceState.service;
+ }
+ }
+ }
+ try {
+ if (service != null) {
+ List<String> interfaces = new ArrayList<>();
+ for (final String name : CollectionUtils.emptyIfNull(
+ service.getAvailableExtensionInterfaceNames())) {
+ String permission = service.getExtensionInterfacePermission(name);
+ if (permission == null
+ || mContext.checkPermission(permission, callingPid, callingUid)
+ == PackageManager.PERMISSION_GRANTED) {
+ interfaces.add(name);
+ }
+ }
+ return interfaces;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in getAvailableExtensionInterfaceNames "
+ + "or getExtensionInterfacePermission", e);
+ }
+ return new ArrayList<>();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public IBinder getExtensionInterface(String inputId, String name, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid,
+ userId, "getExtensionInterface");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ITvInputService service = null;
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+ TvInputState inputState = userState.inputMap.get(inputId);
+ if (inputState != null) {
+ ServiceState serviceState =
+ userState.serviceStateMap.get(inputState.info.getComponent());
+ if (serviceState != null && serviceState.isHardware
+ && serviceState.service != null) {
+ service = serviceState.service;
+ }
+ }
+ }
+ try {
+ if (service != null) {
+ String permission = service.getExtensionInterfacePermission(name);
+ if (permission == null
+ || mContext.checkPermission(permission, callingPid, callingUid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return service.getExtensionInterface(name);
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in getExtensionInterfacePermission "
+ + "or getExtensionInterface", e);
+ }
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId) {
if (mContext.checkCallingPermission(
android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS)
diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
index 2ca348b3ae46..63daa3503bd5 100644
--- a/services/core/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/core/jni/com_android_server_ConsumerIrService.cpp
@@ -34,7 +34,7 @@ namespace android {
static sp<IConsumerIr> mHal;
-static jboolean halOpen(JNIEnv* /* env */, jobject /* obj */) {
+static jboolean getHidlHalService(JNIEnv * /* env */, jobject /* obj */) {
// TODO(b/31632518)
mHal = IConsumerIr::getService();
return mHal != nullptr;
@@ -84,9 +84,9 @@ static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject /* obj */) {
}
static const JNINativeMethod method_table[] = {
- { "halOpen", "()Z", (void *)halOpen },
- { "halTransmit", "(I[I)I", (void *)halTransmit },
- { "halGetCarrierFrequencies", "()[I", (void *)halGetCarrierFrequencies},
+ {"getHidlHalService", "()Z", (void *)getHidlHalService},
+ {"halTransmit", "(I[I)I", (void *)halTransmit},
+ {"halGetCarrierFrequencies", "()[I", (void *)halGetCarrierFrequencies},
};
int register_android_server_ConsumerIrService(JNIEnv *env) {