From 558acf96dbffc0f13b414b1a5c5de191f6ffe27a Mon Sep 17 00:00:00 2001 From: Conrad Chen Date: Wed, 5 Apr 2017 17:31:01 -0700 Subject: [PATCH] TIF: add TvInputManager methods to notify apps Adds TvInputManager methods to notify apps with protected broadcasts for: 1. Disabling browsable state of preview and watch next programs. 2. Adding preview programs to watch next programs. Test: build and verify manually to check if notifications are broadcasted. Bug: 35881266 Change-Id: I20fd5b63f42b2c74277315bbbd251b71c649e5c1 --- api/system-current.txt | 4 ++ core/res/AndroidManifest.xml | 10 ++++ .../android/media/tv/ITvInputManager.aidl | 4 ++ .../java/android/media/tv/TvInputManager.java | 59 +++++++++++++++++++ .../server/tv/TvInputManagerService.java | 44 ++++++++++++++ .../java/com/android/server/SystemServer.java | 3 +- 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/api/system-current.txt b/api/system-current.txt index fa2a69ece6f71..fc567b9afab95 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"; @@ -27006,6 +27007,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 0a50048c51490..866c47e2efede 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -531,6 +531,9 @@ + + + @@ -2511,6 +2514,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 a5eac46281f35..e4be27b5bba21 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1423,7 +1423,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();