diff options
| -rw-r--r-- | core/api/system-current.txt | 5 | ||||
| -rw-r--r-- | core/jni/OWNERS | 6 | ||||
| -rw-r--r-- | media/java/android/media/tv/ITvInputManager.aidl | 2 | ||||
| -rwxr-xr-x | media/java/android/media/tv/ITvInputService.aidl | 23 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvInputManager.java | 51 | ||||
| -rwxr-xr-x | media/java/android/media/tv/TvInputService.java | 76 | ||||
| -rw-r--r-- | services/core/Android.bp | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ConsumerIrService.java | 60 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/tv/TvInputManagerService.java | 86 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_ConsumerIrService.cpp | 8 |
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) { |