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();