TIF: add helper methods for making a channel browsable.
Test: build and manually tested with a local app.
Bug: 36395259, Bug: 36097352
Change-Id: I512ed6f4da21af01445fdbcd2f200a681c5dde19
diff --git a/api/current.txt b/api/current.txt
index 5955bd4..645271d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24510,14 +24510,14 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index d565b41..5e6bc8a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -26483,10 +26483,12 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
+ field public static final java.lang.String ACTION_CHANNEL_BROWSABLE_REQUESTED = "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
diff --git a/api/test-current.txt b/api/test-current.txt
index 9ba8e57..95a52ed 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -24623,14 +24623,14 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8895877..8225494 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -535,6 +535,7 @@
<protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" />
<protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
<protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
+ <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index af4a5be..b076bb6 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -107,6 +107,7 @@
List<DvbDeviceInfo> getDvbDeviceList();
ParcelFileDescriptor openDvbDevice(in DvbDeviceInfo info, int device);
- // For preview programs
+ // For preview channels and programs
void sendTvInputNotifyIntent(in Intent intent, int userId);
+ void requestChannelBrowsable(in Uri channelUri, int userId);
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 6635b5f..9d6d98e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -21,9 +21,11 @@
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
+import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -75,8 +77,9 @@
private static final String PATH_PASSTHROUGH = "passthrough";
/**
- * Activity Action: sent by an application telling the system to set the given channel as
- * browsable. This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+ * Broadcast Action: sent when an application requests the system to make the given channel
+ * browsable. The operation is performed in the background without user interaction. This
+ * is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
*
* <p>The intent must contain the following bundle parameters:
* <ul>
@@ -84,9 +87,26 @@
* integer.</li>
* <li>{@link #EXTRA_PACKAGE_NAME}: the package name of the requesting application.</li>
* </ul>
+ * @hide
*/
- public static final String ACTION_MAKE_CHANNEL_BROWSABLE =
- "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+ @SystemApi
+ public static final String ACTION_CHANNEL_BROWSABLE_REQUESTED =
+ "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
+
+ /**
+ * Activity Action: sent by an application telling the system to make the given channel
+ * browsable with user interaction. The system may show UI to ask user to approve the channel.
+ * This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type. Use
+ * {@link Activity#startActivityForResult} to get the result of the request.
+ *
+ * <p>The intent must contain the following bundle parameters:
+ * <ul>
+ * <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
+ * integer.</li>
+ * </ul>
+ */
+ public static final String ACTION_REQUEST_CHANNEL_BROWSABLE =
+ "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
/**
* Broadcast Action: sent by the system to tell the target TV input that one of its preview
@@ -146,10 +166,16 @@
public static final String ACTION_INITIALIZE_PROGRAMS =
"android.media.tv.action.INITIALIZE_PROGRAMS";
- /** The key for a bundle parameter containing a channel ID as a long integer */
+ /**
+ * The key for a bundle parameter containing a channel ID as a long integer
+ */
public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- /** The key for a bundle parameter containing a package name as a string. */
+ /**
+ * The key for a bundle parameter containing a package name as a string.
+ * @hide
+ */
+ @SystemApi
public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
/** The key for a bundle parameter containing a program ID as a long integer. */
@@ -565,6 +591,24 @@
return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
}
+ /**
+ * Requests to make a channel browsable.
+ *
+ * <p>Once called, the system will review the request and make the channel browsable based on
+ * its policy. The first request from a package is guaranteed to be approved. This is only
+ * relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+ *
+ * @param context The context for accessing content provider.
+ * @param channelId The channel ID to be browsable.
+ * @see Channels#COLUMN_BROWSABLE
+ */
+ public static void requestChannelBrowsable(Context context, long channelId) {
+ TvInputManager manager = (TvInputManager) context.getSystemService(
+ Context.TV_INPUT_SERVICE);
+ if (manager != null) {
+ manager.requestChannelBrowsable(buildChannelUri(channelId));
+ }
+ }
private TvContract() {}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 276a0dc..68ee02c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1681,6 +1681,23 @@
}
/**
+ * Requests to make a channel browsable.
+ *
+ * <p>Once called, the system will review the request and make the channel browsable based on
+ * its policy. The first request from a package is guaranteed to be approved.
+ *
+ * @param channelUri The URI for the channel to be browsable.
+ * @hide
+ */
+ public void requestChannelBrowsable(Uri channelUri) {
+ try {
+ mService.requestChannelBrowsable(channelUri, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* The Session provides the per-session functionality of TV inputs.
* @hide
*/
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index a519acc..25a0772 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1954,6 +1954,33 @@
}
@Override
+ public void requestChannelBrowsable(Uri channelUri, int userId)
+ throws RemoteException {
+ final String callingPackageName = getCallingPackageName();
+ final long identity = Binder.clearCallingIdentity();
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "requestChannelBrowsable");
+ try {
+ Intent intent = new Intent(TvContract.ACTION_CHANNEL_BROWSABLE_REQUESTED);
+ List<ResolveInfo> list = getContext().getPackageManager()
+ .queryBroadcastReceivers(intent, 0);
+ if (list != null) {
+ for (ResolveInfo info : list) {
+ String receiverPackageName = info.activityInfo.packageName;
+ intent.putExtra(TvContract.EXTRA_CHANNEL_ID, ContentUris.parseId(
+ channelUri));
+ intent.putExtra(TvContract.EXTRA_PACKAGE_NAME, callingPackageName);
+ intent.setPackage(receiverPackageName);
+ getContext().sendBroadcastAsUser(intent, new UserHandle(resolvedUserId));
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
@SuppressWarnings("resource")
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");