diff --git a/api/system-current.txt b/api/system-current.txt index 111a37803f713..025f5bfcc4999 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -163,6 +163,7 @@ package android { field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final java.lang.String NFC = "android.permission.NFC"; field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP"; + field public static final java.lang.String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS"; field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG"; field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS"; field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT"; @@ -26969,6 +26970,9 @@ package android.media.tv { method public boolean isParentalControlsEnabled(); method public boolean isRatingBlocked(android.media.tv.TvContentRating); method public boolean isSingleSessionActive(); + method public void notifyPreviewProgramAddedToWatchNext(java.lang.String, long, long); + method public void notifyPreviewProgramBrowsableDisabled(java.lang.String, long); + method public void notifyWatchNextProgramBrowsableDisabled(java.lang.String, long); method public void registerCallback(android.media.tv.TvInputManager.TvInputCallback, android.os.Handler); method public void releaseTvInputHardware(int, android.media.tv.TvInputManager.Hardware); method public void removeBlockedRating(android.media.tv.TvContentRating); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f1cce0cf3f455..14c79e0f1e059 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -533,6 +533,9 @@ + + + @@ -2520,6 +2523,13 @@ + + + diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 0d51b5b508b84..af4a5bed97438 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -17,6 +17,7 @@ package android.media.tv; import android.content.ComponentName; +import android.content.Intent; import android.graphics.Rect; import android.media.PlaybackParams; import android.media.tv.DvbDeviceInfo; @@ -105,4 +106,7 @@ interface ITvInputManager { // For DVB device binding List getDvbDeviceList(); ParcelFileDescriptor openDvbDevice(in DvbDeviceInfo info, int device); + + // For preview programs + void sendTvInputNotifyIntent(in Intent intent, int userId); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 09b2050b1b1ae..276a0dcb01ee7 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.content.Intent; import android.graphics.Rect; import android.media.PlaybackParams; import android.net.Uri; @@ -1393,6 +1394,64 @@ public final class TvInputManager { } } + /** + * Notifies the TV input of the given preview program that the program's browsable state is + * disabled. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) + public void notifyPreviewProgramBrowsableDisabled(String packageName, long programId) { + Intent intent = new Intent(); + intent.setAction(TvContract.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED); + intent.putExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, programId); + intent.setPackage(packageName); + try { + mService.sendTvInputNotifyIntent(intent, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Notifies the TV input of the given watch next program that the program's browsable state is + * disabled. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) + public void notifyWatchNextProgramBrowsableDisabled(String packageName, long programId) { + Intent intent = new Intent(); + intent.setAction(TvContract.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED); + intent.putExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, programId); + intent.setPackage(packageName); + try { + mService.sendTvInputNotifyIntent(intent, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Notifies the TV input of the given preview program that the program is added to watch next. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) + public void notifyPreviewProgramAddedToWatchNext(String packageName, long previewProgramId, + long watchNextProgramId) { + Intent intent = new Intent(); + intent.setAction(TvContract.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT); + intent.putExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, previewProgramId); + intent.putExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, watchNextProgramId); + intent.setPackage(packageName); + try { + mService.sendTvInputNotifyIntent(intent, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Creates a {@link Session} for a given TV input. * diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index be91f48fb76fd..a519acc9e8fae 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -941,6 +941,50 @@ public final class TvInputManagerService extends SystemService { } } + @Override + public void sendTvInputNotifyIntent(Intent intent, int userId) { + if (mContext.checkCallingPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("The caller: " + getCallingPackageName() + + " doesn't have permission: " + + android.Manifest.permission.NOTIFY_TV_INPUTS); + } + if (TextUtils.isEmpty(intent.getPackage())) { + throw new IllegalArgumentException("Must specify package name to notify."); + } + switch (intent.getAction()) { + case TvContract.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED: + if (intent.getLongExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, -1) < 0) { + throw new IllegalArgumentException("Invalid preview program ID."); + } + break; + case TvContract.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED: + if (intent.getLongExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, -1) < 0) { + throw new IllegalArgumentException("Invalid watch next program ID."); + } + break; + case TvContract.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT: + if (intent.getLongExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, -1) < 0) { + throw new IllegalArgumentException("Invalid preview program ID."); + } + if (intent.getLongExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, -1) < 0) { + throw new IllegalArgumentException("Invalid watch next program ID."); + } + break; + default: + throw new IllegalArgumentException("Invalid TV input notifying action: " + + intent.getAction()); + } + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), + Binder.getCallingUid(), userId, "sendTvInputNotifyIntent"); + final long identity = Binder.clearCallingIdentity(); + try { + getContext().sendBroadcastAsUser(intent, new UserHandle(resolvedUserId)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public void registerCallback(final ITvInputManagerCallback callback, int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f74512a001229..e47da552c7178 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1437,7 +1437,8 @@ public final class SystemServer { traceEnd(); } - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)) { + if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV) + || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { traceBeginAndSlog("StartTvInputManager"); mSystemServiceManager.startService(TvInputManagerService.class); traceEnd();