TIF: Do not log non-searchable channel watch history
Bug: 16798476
Change-Id: Ic131009ad65a661331e4f8f0820c5c183a9f4986
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 5a0ea0d..a826957 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
+import android.media.tv.TvContract.Programs;
import android.net.Uri;
import android.provider.BaseColumns;
import android.util.ArraySet;
@@ -684,10 +685,11 @@
* The flag indicating whether this TV channel is searchable or not.
* <p>
* In some regions, it is not allowed to surface search results for a given channel without
- * broadcaster's consent. This is used to impose such restriction. A value of 1 indicates
- * the channel is searchable and can be included in search results, a value of 0 indicates
- * the channel and its TV programs are hidden from search. If not specified, this value is
- * set to 1 (searchable) by default.
+ * broadcaster's consent. This is used to impose such restriction. Channels marked with
+ * "not searchable" cannot be used by other services except for the system service that
+ * shows the TV content. A value of 1 indicates the channel is searchable and can be
+ * included in search results, a value of 0 indicates the channel and its TV programs are
+ * hidden from search. If not specified, this value is set to 1 (searchable) by default.
* </p><p>
* Type: INTEGER (boolean)
* </p>
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index c095905..14d1ec4 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -35,7 +35,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Rect;
import android.hardware.hdmi.HdmiDeviceInfo;
@@ -283,7 +282,6 @@
userState.inputMap.clear();
userState.inputMap = inputMap;
- Resources r = Resources.getSystem();
userState.ratingSystemXmlUriSet.clear();
userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML);
for (TvInputState state : userState.inputMap.values()) {
@@ -1262,6 +1260,7 @@
args.arg1 = sessionState.mLogUri;
args.arg2 = ContentUris.parseId(channelUri);
args.arg3 = currentTime;
+ args.arg4 = sessionState;
mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget();
} catch (RemoteException e) {
Slog.e(TAG, "error in tune", e);
@@ -2076,7 +2075,8 @@
Uri uri = (Uri) args.arg1;
long channelId = (long) args.arg2;
long time = (long) args.arg3;
- onOpenEntry(uri, channelId, time);
+ SessionState sessionState = (SessionState) args.arg4;
+ onOpenEntry(uri, channelId, time, sessionState);
args.recycle();
return;
}
@@ -2085,7 +2085,8 @@
Uri uri = (Uri) args.arg1;
long channelId = (long) args.arg2;
long time = (long) args.arg3;
- onUpdateEntry(uri, channelId, time);
+ SessionState sessionState = (SessionState) args.arg4;
+ onUpdateEntry(uri, channelId, time, sessionState);
args.recycle();
return;
}
@@ -2104,7 +2105,17 @@
}
}
- private void onOpenEntry(Uri uri, long channelId, long watchStarttime) {
+ private void onOpenEntry(Uri logUri, long channelId, long watchStarttime,
+ SessionState sessionState) {
+ if (!isChannelSearchable(channelId)) {
+ // Do not log anything about non-searchable channels.
+ synchronized (mLock) {
+ sessionState.mLogUri = null;
+ }
+ mContentResolver.delete(logUri, null, null);
+ return;
+ }
+
String[] projection = {
TvContract.Programs.COLUMN_TITLE,
TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
@@ -2132,11 +2143,11 @@
long endTime = cursor.getLong(2);
values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime);
values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3));
- mContentResolver.update(uri, values, null, null);
+ mContentResolver.update(logUri, values, null, null);
// Schedule an update when the current program ends.
SomeArgs args = SomeArgs.obtain();
- args.arg1 = uri;
+ args.arg1 = logUri;
args.arg2 = channelId;
args.arg3 = endTime;
Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args);
@@ -2149,7 +2160,7 @@
}
}
- private void onUpdateEntry(Uri uri, long channelId, long time) {
+ private void onUpdateEntry(Uri uri, long channelId, long time, SessionState sessionState) {
String[] projection = {
TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS,
TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS,
@@ -2193,7 +2204,7 @@
}
}
// Re-open the current log entry with the next program information.
- onOpenEntry(uri, channelId, time);
+ onOpenEntry(uri, channelId, time, sessionState);
}
private void onCloseEntry(Uri uri, long watchEndTime) {
@@ -2201,6 +2212,26 @@
values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime);
mContentResolver.update(uri, values, null, null);
}
+
+ private boolean isChannelSearchable(long channelId) {
+ String[] projection = { TvContract.Channels.COLUMN_SEARCHABLE };
+ String selection = TvContract.Channels._ID + "=?";
+ String[] selectionArgs = { String.valueOf(channelId) };
+ Cursor cursor = null;
+ try {
+ cursor = mContentResolver.query(TvContract.Channels.CONTENT_URI, projection,
+ selection, selectionArgs, null);
+ if (cursor != null && cursor.moveToNext()) {
+ return cursor.getLong(0) == 1 ? true : false;
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ // Unless explicitly specified non-searchable, by default the channel is searchable.
+ return true;
+ }
}
final class HardwareListener implements TvInputHardwareManager.Listener {