diff options
Diffstat (limited to 'tests/common/src/com/android/tv/testing/data/ChannelUtils.java')
-rw-r--r-- | tests/common/src/com/android/tv/testing/data/ChannelUtils.java | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/tests/common/src/com/android/tv/testing/data/ChannelUtils.java b/tests/common/src/com/android/tv/testing/data/ChannelUtils.java new file mode 100644 index 00000000..920c7087 --- /dev/null +++ b/tests/common/src/com/android/tv/testing/data/ChannelUtils.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tv.testing.data; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.media.tv.TvContract; +import android.media.tv.TvContract.Channels; +import android.net.Uri; +import android.os.AsyncTask; +import android.support.annotation.WorkerThread; +import android.text.TextUtils; +import android.util.Log; +import android.util.SparseArray; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Static helper methods for working with {@link android.media.tv.TvContract}. */ +public class ChannelUtils { + private static final String TAG = "ChannelUtils"; + private static final boolean DEBUG = false; + + /** + * Query and return the map of (channel_id, ChannelInfo). See: {@link + * com.android.tv.testing.data.ChannelInfo#fromCursor(Cursor)}. + */ + @WorkerThread + public static Map<Long, ChannelInfo> queryChannelInfoMapForTvInput( + Context context, String inputId) { + Uri uri = TvContract.buildChannelsUriForInput(inputId); + Map<Long, ChannelInfo> map = new HashMap<>(); + + String[] projections = new String[ChannelInfo.PROJECTION.length + 1]; + projections[0] = Channels._ID; + System.arraycopy(ChannelInfo.PROJECTION, 0, projections, 1, ChannelInfo.PROJECTION.length); + try (Cursor cursor = + context.getContentResolver().query(uri, projections, null, null, null)) { + if (cursor != null) { + while (cursor.moveToNext()) { + map.put(cursor.getLong(0), ChannelInfo.fromCursor(cursor)); + } + } + return map; + } + } + + @WorkerThread + public static void updateChannels(Context context, String inputId, List<ChannelInfo> channels) { + // Create a map from original network ID to channel row ID for existing channels. + SparseArray<Long> existingChannelsMap = new SparseArray<>(); + Uri channelsUri = TvContract.buildChannelsUriForInput(inputId); + String[] projection = {Channels._ID, Channels.COLUMN_ORIGINAL_NETWORK_ID}; + ContentResolver resolver = context.getContentResolver(); + try (Cursor cursor = resolver.query(channelsUri, projection, null, null, null)) { + while (cursor != null && cursor.moveToNext()) { + long rowId = cursor.getLong(0); + int originalNetworkId = cursor.getInt(1); + existingChannelsMap.put(originalNetworkId, rowId); + } + } + + Map<Uri, String> logos = new HashMap<>(); + for (ChannelInfo channel : channels) { + // If a channel exists, update it. If not, insert a new one. + ContentValues values = new ContentValues(); + values.put(Channels.COLUMN_INPUT_ID, inputId); + values.put(Channels.COLUMN_DISPLAY_NUMBER, channel.number); + values.put(Channels.COLUMN_DISPLAY_NAME, channel.name); + values.put(Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.originalNetworkId); + String videoFormat = channel.getVideoFormat(); + if (videoFormat != null) { + values.put(Channels.COLUMN_VIDEO_FORMAT, videoFormat); + } else { + values.putNull(Channels.COLUMN_VIDEO_FORMAT); + } + if (!TextUtils.isEmpty(channel.appLinkText)) { + values.put(Channels.COLUMN_APP_LINK_TEXT, channel.appLinkText); + } + if (channel.appLinkColor != 0) { + values.put(Channels.COLUMN_APP_LINK_COLOR, channel.appLinkColor); + } + if (!TextUtils.isEmpty(channel.appLinkPosterArtUri)) { + values.put(Channels.COLUMN_APP_LINK_POSTER_ART_URI, channel.appLinkPosterArtUri); + } + if (!TextUtils.isEmpty(channel.appLinkIconUri)) { + values.put(Channels.COLUMN_APP_LINK_ICON_URI, channel.appLinkIconUri); + } + if (!TextUtils.isEmpty(channel.appLinkIntentUri)) { + values.put(Channels.COLUMN_APP_LINK_INTENT_URI, channel.appLinkIntentUri); + } + Long rowId = existingChannelsMap.get(channel.originalNetworkId); + Uri uri; + if (rowId == null) { + if (DEBUG) { + Log.d(TAG, "Inserting " + channel); + } + uri = resolver.insert(TvContract.Channels.CONTENT_URI, values); + } else { + if (DEBUG) { + Log.d(TAG, "Updating " + channel); + } + uri = TvContract.buildChannelUri(rowId); + resolver.update(uri, values, null, null); + existingChannelsMap.remove(channel.originalNetworkId); + } + if (!TextUtils.isEmpty(channel.logoUrl)) { + logos.put(TvContract.buildChannelLogoUri(uri), channel.logoUrl); + } + } + if (!logos.isEmpty()) { + new InsertLogosTask(context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, logos); + } + + // Deletes channels which don't exist in the new feed. + int size = existingChannelsMap.size(); + for (int i = 0; i < size; ++i) { + Long rowId = existingChannelsMap.valueAt(i); + resolver.delete(TvContract.buildChannelUri(rowId), null, null); + } + } + + public static void copy(InputStream is, OutputStream os) throws IOException { + byte[] buffer = new byte[1024]; + int len; + while ((len = is.read(buffer)) != -1) { + os.write(buffer, 0, len); + } + } + + private ChannelUtils() { + // Prevent instantiation. + } + + public static List<ChannelInfo> createChannelInfos(Context context, int channelCount) { + List<ChannelInfo> channels = new ArrayList<>(); + for (int i = 1; i <= channelCount; i++) { + channels.add(ChannelInfo.create(context, i)); + } + return channels; + } + + public static class InsertLogosTask extends AsyncTask<Map<Uri, String>, Void, Void> { + private final Context mContext; + + InsertLogosTask(Context context) { + mContext = context; + } + + @SafeVarargs + @Override + public final Void doInBackground(Map<Uri, String>... logosList) { + for (Map<Uri, String> logos : logosList) { + for (Uri uri : logos.keySet()) { + if (uri == null) { + continue; + } + Uri logoUri = Uri.parse(logos.get(uri)); + try (InputStream is = mContext.getContentResolver().openInputStream(logoUri); + OutputStream os = mContext.getContentResolver().openOutputStream(uri)) { + copy(is, os); + } catch (IOException ioe) { + Log.e(TAG, "Failed to write " + logoUri + " to " + uri, ioe); + } + } + } + return null; + } + } +} |