diff options
| -rw-r--r-- | core/api/system-current.txt | 5 | ||||
| -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 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/tv/TvInputManagerService.java | 86 |
6 files changed, 233 insertions, 10 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 4a732e544722..98d0b2d9820d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5814,9 +5814,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(); @@ -5847,6 +5849,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/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/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 36a854e5374c..983d15985310 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; @@ -1162,6 +1163,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) |