13f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho/* 2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project 33f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * 43f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * Licensed under the Apache License, Version 2.0 (the "License"); 53f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * you may not use this file except in compliance with the License. 63f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * You may obtain a copy of the License at 73f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * 83f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * http://www.apache.org/licenses/LICENSE-2.0 93f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * 103f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * Unless required by applicable law or agreed to in writing, software 113f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * distributed under the License is distributed on an "AS IS" BASIS, 123f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * See the License for the specific language governing permissions and 143f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * limitations under the License. 153f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho */ 163f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 17d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leepackage com.android.tv.util; 183f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 19816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.annotation.SuppressLint; 207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.ComponentName; 21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.ContentResolver; 228f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seoimport android.content.ContentValues; 233f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Choimport android.content.Context; 24c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Choimport android.content.Intent; 255980d6736ab06e8c15eebb151a3b0c8d943b37b8Jae Seoimport android.content.pm.PackageManager; 267d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.res.ColorStateList; 2748dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.content.res.Configuration; 287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.res.Resources; 297d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.content.res.Resources.Theme; 303f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Choimport android.database.Cursor; 319035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvContract; 32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContract.Channels; 339035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo; 34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvTrackInfo; 353f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Choimport android.net.Uri; 367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.os.Build; 374ffb471c39be6b915ad2396887fab450dc262600Youngsang Choimport android.preference.PreferenceManager; 38816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.support.annotation.Nullable; 39816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.support.annotation.VisibleForTesting; 4007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.support.annotation.WorkerThread; 414ffb471c39be6b915ad2396887fab450dc262600Youngsang Choimport android.text.TextUtils; 42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.format.DateUtils; 43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log; 44816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.view.View; 4548dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.widget.Toast; 463f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 47816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.R; 487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.TvApplication; 49d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel; 50d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Program; 5121abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo; 52ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 531abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.text.SimpleDateFormat; 54816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.ArrayList; 55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Calendar; 567d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport java.util.Collection; 57816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Date; 58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.HashSet; 59c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Choimport java.util.List; 60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Locale; 61816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Set; 62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.TimeZone; 63816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.TimeUnit; 64c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho 653f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho/** 663f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho * A class that includes convenience methods for accessing TvProvider database. 673f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho */ 68fd85048121f09be7722700cdc78e463e93f6cc5bYoungsang Chopublic class Utils { 69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String TAG = "Utils"; 70816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final boolean DEBUG = false; 71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private static final SimpleDateFormat ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); 731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final String EXTRA_KEY_KEYCODE = "keycode"; 75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final String EXTRA_KEY_ACTION = "action"; 76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final String EXTRA_ACTION_SHOW_TV_INPUT ="show_tv_input"; 77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final String EXTRA_KEY_FROM_LAUNCHER = "from_launcher"; 78ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public static final String EXTRA_KEY_RECORDING_URI = "recording_uri"; 79816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Query parameter in the intent of starting MainActivity. 81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static final String PARAM_SOURCE = "source"; 824ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho 83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PATH_CHANNEL = "channel"; 84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PATH_PROGRAM = "program"; 858f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo 86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_LAST_WATCHED_CHANNEL_ID = "last_watched_channel_id"; 87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_LAST_WATCHED_CHANNEL_ID_FOR_INPUT = 88816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko "last_watched_channel_id_for_input_"; 89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_LAST_WATCHED_CHANNEL_URI = "last_watched_channel_uri"; 90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 91816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_SD_WIDTH = 704; 92816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_SD_HEIGHT = 480; 93816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_HD_WIDTH = 1280; 94816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_HD_HEIGHT = 720; 95816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_FULL_HD_WIDTH = 1920; 96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_FULL_HD_HEIGHT = 1080; 97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_ULTRA_HD_WIDTH = 2048; 98816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int VIDEO_ULTRA_HD_HEIGHT = 1536; 99816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 100816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int AUDIO_CHANNEL_NONE = 0; 101816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int AUDIO_CHANNEL_MONO = 1; 102816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int AUDIO_CHANNEL_STEREO = 2; 103816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int AUDIO_CHANNEL_SURROUND_6 = 6; 104816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final int AUDIO_CHANNEL_SURROUND_8 = 8; 10521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang 106e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim private enum AspectRatio { 107e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim ASPECT_RATIO_4_3(4, 3), 108e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim ASPECT_RATIO_16_9(16, 9), 109e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim ASPECT_RATIO_21_9(21, 9); 110e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 111e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim final int width; 112e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim final int height; 113e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 114e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim AspectRatio(int width, int height) { 115e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim this.width = width; 116e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim this.height = height; 117e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 118e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 1198f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo @Override 120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @SuppressLint("DefaultLocale") 121e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim public String toString() { 122e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return String.format("%d:%d", width, height); 123e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 124e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 125e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private Utils() { 127900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 128900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String buildSelectionForIds(String idName, List<Long> ids) { 130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko StringBuilder sb = new StringBuilder(); 131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sb.append(idName).append(" in (") 132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .append(ids.get(0)); 133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (int i = 1; i < ids.size(); ++i) { 134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sb.append(",").append(ids.get(i)); 1353f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko sb.append(")"); 137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return sb.toString(); 1383f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 1393f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 14007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko @WorkerThread 141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getInputIdForChannel(Context context, long channelId) { 142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (channelId == Channel.INVALID_ID) { 1433f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho return null; 1443f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Uri channelUri = TvContract.buildChannelUri(channelId); 146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String[] projection = {TvContract.Channels.COLUMN_INPUT_ID}; 147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try (Cursor cursor = context.getContentResolver() 148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .query(channelUri, projection, null, null, null)) { 1495e91a958ffdfcae33dd0614fe683b64535d76e03Chulwoo Lee if (cursor != null && cursor.moveToNext()) { 150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return Utils.intern(cursor.getString(0)); 1515e91a958ffdfcae33dd0614fe683b64535d76e03Chulwoo Lee } 1523f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 1535e91a958ffdfcae33dd0614fe683b64535d76e03Chulwoo Lee return null; 1543f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 1553f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static void setLastWatchedChannel(Context context, Channel channel) { 157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (channel == null) { 158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.e(TAG, "setLastWatchedChannel: channel cannot be null"); 159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 1604ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho } 161dbe4746286fb0dcdf24a89fb4a08b620c5e71b05Jaekyun Seok PreferenceManager.getDefaultSharedPreferences(context).edit() 162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .putString(PREF_KEY_LAST_WATCHED_CHANNEL_URI, channel.getUri().toString()).apply(); 163816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!channel.isPassthrough()) { 164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long channelId = channel.getId(); 165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (channel.getId() < 0) { 166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalArgumentException("channelId should be equal to or larger than 0"); 167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko PreferenceManager.getDefaultSharedPreferences(context).edit() 169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .putLong(PREF_KEY_LAST_WATCHED_CHANNEL_ID, channelId).apply(); 170816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko PreferenceManager.getDefaultSharedPreferences(context).edit() 171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .putLong(PREF_KEY_LAST_WATCHED_CHANNEL_ID_FOR_INPUT + channel.getInputId(), 172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko channelId).apply(); 173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 1744ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho } 1754ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho 176900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public static long getLastWatchedChannelId(Context context) { 177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return PreferenceManager.getDefaultSharedPreferences(context) 178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .getLong(PREF_KEY_LAST_WATCHED_CHANNEL_ID, Channel.INVALID_ID); 1794ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho } 1804ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho 181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static long getLastWatchedChannelIdForInput(Context context, String inputId) { 182816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return PreferenceManager.getDefaultSharedPreferences(context) 183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .getLong(PREF_KEY_LAST_WATCHED_CHANNEL_ID_FOR_INPUT + inputId, Channel.INVALID_ID); 1843f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho } 1853f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho 186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getLastWatchedChannelUri(Context context) { 18756008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho return PreferenceManager.getDefaultSharedPreferences(context) 188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko .getString(PREF_KEY_LAST_WATCHED_CHANNEL_URI, null); 18956008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho } 19056008ca02c3d40e73fe6229b9eb95277d5c57129Youngsang Cho 191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns {@code true}, if {@code uri} specifies an input, which is usually generated 193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * from {@link TvContract#buildChannelsUriForInput}. 194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isChannelUriForInput(Uri uri) { 196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return isTvUri(uri) && PATH_CHANNEL.equals(uri.getPathSegments().get(0)) 197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko && !TextUtils.isEmpty(uri.getQueryParameter("input")); 198dbe4746286fb0dcdf24a89fb4a08b620c5e71b05Jaekyun Seok } 199dbe4746286fb0dcdf24a89fb4a08b620c5e71b05Jaekyun Seok 200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns {@code true}, if {@code uri} is a channel URI for a specific channel. It is copied 202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * from the hidden method TvContract.isChannelUri. 203816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 204816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isChannelUriForOneChannel(Uri uri) { 205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return isChannelUriForTunerInput(uri) || TvContract.isChannelUriForPassthroughInput(uri); 206816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 208816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 209816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns {@code true}, if {@code uri} is a channel URI for a tuner input. It is copied from 210816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * the hidden method TvContract.isChannelUriForTunerInput. 211816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isChannelUriForTunerInput(Uri uri) { 213816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL); 214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 215816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 216816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static boolean isTvUri(Uri uri) { 217816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) 218816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko && TvContract.AUTHORITY.equals(uri.getAuthority()); 219816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static boolean isTwoSegmentUriStartingWith(Uri uri, String pathSegment) { 222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko List<String> pathSegments = uri.getPathSegments(); 223816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return pathSegments.size() == 2 && pathSegment.equals(pathSegments.get(0)); 224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 226816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 227816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns {@code true}, if {@code uri} is a programs URI. 228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isProgramsUri(Uri uri) { 230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return isTvUri(uri) && PATH_PROGRAM.equals(uri.getPathSegments().get(0)); 231816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 232816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 233816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 234816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Gets the info of the program on particular time. 235816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 23607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko @WorkerThread 237816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static Program getProgramAt(Context context, long channelId, long timeMs) { 2388f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo if (channelId == Channel.INVALID_ID) { 239816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.e(TAG, "getCurrentProgramAt - channelId is invalid"); 240816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return null; 2418f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 242816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (context.getMainLooper().getThread().equals(Thread.currentThread())) { 243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String message = "getCurrentProgramAt called on main thread"; 244816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) { 245816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Generating a stack trace can be expensive, only do it in debug mode. 246816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, message, new IllegalStateException(message)); 247816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else { 248816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.w(TAG, message); 2498f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 250816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Uri uri = TvContract.buildProgramsUriForChannel(TvContract.buildChannelUri(channelId), 252816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko timeMs, timeMs); 253816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try (Cursor cursor = context.getContentResolver().query(uri, Program.PROJECTION, 254816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko null, null, null)) { 255816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (cursor != null && cursor.moveToNext()) { 256816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return Program.fromCursor(cursor); 2578f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 2588f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 259816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return null; 260816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 2618f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo 262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Gets the info of the current program. 264816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 26507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko @WorkerThread 266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static Program getCurrentProgram(Context context, long channelId) { 267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return getProgramAt(context, channelId, System.currentTimeMillis()); 2688f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo } 2698f1ff2894363afbb6909a3a1edc1f3cbe8657c11Jae Seo 270816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns duration string according to the date & time format. 272816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * If {@code startUtcMillis} and {@code endUtcMills} are equal, 273816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * formatted time will be returned instead. 274816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 275816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param startUtcMillis start of duration in millis. Should be less than {code endUtcMillis}. 276816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param endUtcMillis end of duration in millis. Should be larger than {@code startUtcMillis}. 277816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param useShortFormat {@code true} if abbreviation is needed to save space. 278816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * In that case, date will be omitted if duration starts from today 279816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * and is less than a day. If it's necessary, 280816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * {@link DateUtils#FORMAT_NUMERIC_DATE} is used otherwise. 281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 282816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getDurationString( 283816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Context context, long startUtcMillis, long endUtcMillis, boolean useShortFormat) { 28407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko return getDurationString(context, System.currentTimeMillis(), startUtcMillis, endUtcMillis, 28507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko useShortFormat, 0); 286058dc361839df5a41093a4e671466c1977b59fa6Jaekyun Seok } 287058dc361839df5a41093a4e671466c1977b59fa6Jaekyun Seok 288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @VisibleForTesting 289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko static String getDurationString(Context context, long baseMillis, 290816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long startUtcMillis, long endUtcMillis, boolean useShortFormat, int flag) { 291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko flag |= DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_TIME 292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko | ((useShortFormat) ? DateUtils.FORMAT_NUMERIC_DATE : 0); 293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isInGivenDay(baseMillis, startUtcMillis)) { 294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko flag |= DateUtils.FORMAT_SHOW_DATE; 295816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (startUtcMillis != endUtcMillis && useShortFormat) { 297816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Do special handling for 12:00 AM when checking if it's in the given day. 298816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // If it's start, it's considered as beginning of the day. (e.g. 12:00 AM - 12:30 AM) 299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // If it's end, it's considered as end of the day (e.g. 11:00 PM - 12:00 AM) 300816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!isInGivenDay(startUtcMillis, endUtcMillis - 1) 301816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko && endUtcMillis - startUtcMillis < TimeUnit.HOURS.toMillis(11)) { 302816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Do not show date for short format. 303816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Extracting a day is needed because {@link DateUtils@formatDateRange} 304816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // adds date if the duration covers multiple days. 305816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return DateUtils.formatDateRange(context, 306816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko startUtcMillis, endUtcMillis - TimeUnit.DAYS.toMillis(1), flag); 307fe6c711c0321ced102e962c790c8dbc5db9c3257Jaekyun Seok } 308fe6c711c0321ced102e962c790c8dbc5db9c3257Jaekyun Seok } 309816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return DateUtils.formatDateRange(context, startUtcMillis, endUtcMillis, flag); 310fe6c711c0321ced102e962c790c8dbc5db9c3257Jaekyun Seok } 311fe6c711c0321ced102e962c790c8dbc5db9c3257Jaekyun Seok 312816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @VisibleForTesting 313816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isInGivenDay(long dayToMatchInMillis, long subjectTimeInMillis) { 314816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko final long DAY_IN_MS = TimeUnit.DAYS.toMillis(1); 315816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko TimeZone timeZone = Calendar.getInstance().getTimeZone(); 316816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko long offset = timeZone.getRawOffset(); 317816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (timeZone.inDaylightTime(new Date(dayToMatchInMillis))) { 318816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko offset += timeZone.getDSTSavings(); 319816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return Utils.floorTime(dayToMatchInMillis + offset, DAY_IN_MS) 321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko == Utils.floorTime(subjectTimeInMillis + offset, DAY_IN_MS); 322c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho } 323c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho 324e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim public static String getAspectRatioString(int width, int height) { 325e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim if (width == 0 || height == 0) { 326e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return ""; 327e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 328e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 329e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim for (AspectRatio ratio: AspectRatio.values()) { 330e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim if (Math.abs((float) ratio.height / ratio.width - (float) height / width) < 0.05f) { 331e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return ratio.toString(); 332e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 333e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 334e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim return ""; 335e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim } 336e06ded45d6e3b83e1a325e97ccd168c6d1c0d2deJaewan Kim 33748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public static String getAspectRatioString(float videoDisplayAspectRatio) { 33848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (videoDisplayAspectRatio <= 0) { 33948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return ""; 34048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 34148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 34248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho for (AspectRatio ratio : AspectRatio.values()) { 34348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (Math.abs((float) ratio.width / ratio.height - videoDisplayAspectRatio) < 0.05f) { 34448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return ratio.toString(); 34548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 34648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 34748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return ""; 34848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 34948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 35021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang public static int getVideoDefinitionLevelFromSize(int width, int height) { 35121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang if (width >= VIDEO_ULTRA_HD_WIDTH && height >= VIDEO_ULTRA_HD_HEIGHT) { 35221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return StreamInfo.VIDEO_DEFINITION_LEVEL_ULTRA_HD; 35321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } else if (width >= VIDEO_FULL_HD_WIDTH && height >= VIDEO_FULL_HD_HEIGHT) { 35421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return StreamInfo.VIDEO_DEFINITION_LEVEL_FULL_HD; 35521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } else if (width >= VIDEO_HD_WIDTH && height >= VIDEO_HD_HEIGHT) { 35621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return StreamInfo.VIDEO_DEFINITION_LEVEL_HD; 35721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } else if (width >= VIDEO_SD_WIDTH && height >= VIDEO_SD_HEIGHT) { 35821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return StreamInfo.VIDEO_DEFINITION_LEVEL_SD; 35921abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 36021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 36121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 36221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang 363816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getVideoDefinitionLevelString(Context context, int videoFormat) { 36421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang switch (videoFormat) { 36521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang case StreamInfo.VIDEO_DEFINITION_LEVEL_ULTRA_HD: 366816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString( 367816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko R.string.video_definition_level_ultra_hd); 36821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang case StreamInfo.VIDEO_DEFINITION_LEVEL_FULL_HD: 369816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString( 370816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko R.string.video_definition_level_full_hd); 37121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang case StreamInfo.VIDEO_DEFINITION_LEVEL_HD: 372816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.video_definition_level_hd); 37321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang case StreamInfo.VIDEO_DEFINITION_LEVEL_SD: 374816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.video_definition_level_sd); 37521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 37621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return ""; 37721abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 37821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang 379816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getAudioChannelString(Context context, int channelCount) { 380e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang switch (channelCount) { 381e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang case 1: 382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.audio_channel_mono); 383e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang case 2: 384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.audio_channel_stereo); 385e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang case 6: 386816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.audio_channel_5_1); 387f8367f0d7dc6abc4876b52e04e2530c06464698eDongwon Kang case 8: 388816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getResources().getString(R.string.audio_channel_7_1); 389e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 390e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang return ""; 391e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 392e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang 393816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean needToShowSampleRate(Context context, List<TvTrackInfo> tracks) { 394816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Set<String> multiAudioStrings = new HashSet<>(); 395816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (TvTrackInfo track : tracks) { 396816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String multiAudioString = getMultiAudioString(context, track, false); 397816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (multiAudioStrings.contains(multiAudioString)) { 398816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return true; 399816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 400816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko multiAudioStrings.add(multiAudioString); 401816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 402816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return false; 403816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String getMultiAudioString(Context context, TvTrackInfo track, 406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko boolean showSampleRate) { 407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (track.getType() != TvTrackInfo.TYPE_AUDIO) { 408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko throw new IllegalArgumentException("Not an audio track: " + track); 409816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String language = context.getString(R.string.default_language); 4111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (!TextUtils.isEmpty(track.getLanguage())) { 412816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko language = new Locale(track.getLanguage()).getDisplayName(); 4137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 4147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.d(TAG, "No language information found for the audio track: " + track); 415816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 416816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 417816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko StringBuilder metadata = new StringBuilder(); 418816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko switch (track.getAudioChannelCount()) { 419816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case AUDIO_CHANNEL_NONE: 420816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 421816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case AUDIO_CHANNEL_MONO: 422816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(context.getString(R.string.multi_audio_channel_mono)); 423816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 424816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case AUDIO_CHANNEL_STEREO: 425816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(context.getString(R.string.multi_audio_channel_stereo)); 426816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 427816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case AUDIO_CHANNEL_SURROUND_6: 428816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(context.getString(R.string.multi_audio_channel_surround_6)); 429816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 430816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko case AUDIO_CHANNEL_SURROUND_8: 431816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(context.getString(R.string.multi_audio_channel_surround_8)); 432816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko default: 4347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (track.getAudioChannelCount() > 0) { 4357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko metadata.append(context.getString(R.string.multi_audio_channel_suffix, 4367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko track.getAudioChannelCount())); 4377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 4387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.d(TAG, "Invalid audio channel count (" + track.getAudioChannelCount() 4397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko + ") found for the audio track: " + track); 4407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko break; 442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (showSampleRate) { 444816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int sampleRate = track.getAudioSampleRate(); 445816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (sampleRate > 0) { 446816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (metadata.length() > 0) { 447816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(", "); 448816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 449816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int integerPart = sampleRate / 1000; 450816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int tenths = (sampleRate % 1000) / 100; 451816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(integerPart); 452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (tenths != 0) { 453816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append("."); 454816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append(tenths); 455816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 456816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.append("kHz"); 457816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 458816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 459816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 460816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (metadata.length() == 0) { 461816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return language; 462816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 463816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getString(R.string.multi_audio_display_string_with_channel, language, 464816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko metadata.toString()); 465816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 466816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 467816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isEqualLanguage(String lang1, String lang2) { 468816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (lang1 == null) { 469816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return lang2 == null; 470816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } else if (lang2 == null) { 471816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return false; 472816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 473816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try { 474816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return TextUtils.equals( 475816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko new Locale(lang1).getISO3Language(), new Locale(lang2).getISO3Language()); 476816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } catch (Exception ignored) { 477c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho } 478816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return false; 479816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 480c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho 481816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static boolean isIntentAvailable(Context context, Intent intent) { 482816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return context.getPackageManager().queryIntentActivities( 483816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0; 484816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 485816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 486816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 487816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns the label for a given input. Returns the custom label, if any. 488816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 489816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String loadLabel(Context context, TvInputInfo input) { 490816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (input == null) { 491c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho return null; 492c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho } 493816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko CharSequence customLabel = input.loadCustomLabel(context); 494816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko String label = (customLabel == null) ? null : customLabel.toString(); 495816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (TextUtils.isEmpty(label)) { 496816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko label = input.loadLabel(context).toString(); 497c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho } 498816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return label; 499816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 500816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 501816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 502816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Enable all channels synchronously. 503816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 50407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko @WorkerThread 505816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static void enableAllChannels(Context context) { 506816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko ContentValues values = new ContentValues(); 507816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko values.put(Channels.COLUMN_BROWSABLE, 1); 508816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko context.getContentResolver().update(Channels.CONTENT_URI, values, null, null); 509816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 510816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 511816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 512816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Converts time in milliseconds to a String. 513816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 514816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String toTimeString(long timeMillis) { 515816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return new Date(timeMillis).toString(); 516816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 517816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 518816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 5191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Converts time in milliseconds to a ISO 8061 string. 5201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 5211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public static String toIsoDateTimeString(long timeMillis) { 5221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return ISO_8601.format(new Date(timeMillis)); 5231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 5241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 5251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 526816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns a {@link String} object which contains the layout information of the {@code view}. 527816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 528816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String toRectString(View view) { 529816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return "{" 530816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + "l=" + view.getLeft() 531816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ",r=" + view.getRight() 532816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ",t=" + view.getTop() 533816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ",b=" + view.getBottom() 534816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ",w=" + view.getWidth() 535816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ",h=" + view.getHeight() + "}"; 536816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 537816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 538816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 539816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Floors time to the given {@code timeUnit}. For example, if time is 5:32:11 and timeUnit is 540816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * one hour (60 * 60 * 1000), then the output will be 5:00:00. 541816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 542816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static long floorTime(long timeMs, long timeUnit) { 543816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return timeMs - (timeMs % timeUnit); 544816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 545816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 546816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 547816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Ceils time to the given {@code timeUnit}. For example, if time is 5:32:11 and timeUnit is 548816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * one hour (60 * 60 * 1000), then the output will be 6:00:00. 549816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 550816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static long ceilTime(long timeMs, long timeUnit) { 551816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return timeMs + timeUnit - (timeMs % timeUnit); 552c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho } 553c0dbe65141bbf5abe42f77ccda21f9bc44f69b48Youngsang Cho 554816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 555816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns an {@link String#intern() interned} string or null if the input is null. 556816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 557816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko @Nullable 558816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static String intern(@Nullable String string) { 559816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return string == null ? null : string.intern(); 5604ffb471c39be6b915ad2396887fab450dc262600Youngsang Cho } 56107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko 56207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko /** 5637d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Check if the index is valid for the collection, 5647d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @param collection the collection 5657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @param index the index position to test 5667d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @return index >= 0 && index < collection.size(). 5677d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 5687d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public static boolean isIndexValid(@Nullable Collection<?> collection, int index) { 5697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return collection == null ? false : index >= 0 && index < collection.size(); 5707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 5717d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 5727d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko /** 5737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Returns a color integer associated with a particular resource ID. 57407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * 5757d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @see #getColor(android.content.res.Resources,int,Theme) 57607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko */ 5777d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public static int getColor(Resources res, int id) { 5787d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return getColor(res, id, null); 5797d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 5807d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 5817d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko /** 5827d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Returns a color integer associated with a particular resource ID. 5837d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 5847d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * <p>In M version, {@link android.content.res.Resources#getColor(int)} was deprecated and 5857d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * {@link android.content.res.Resources#getColor(int,Theme)} was newly added. 5867d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 5877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @see android.content.res.Resources#getColor(int) 5887d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 5897d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public static int getColor(Resources res, int id, @Nullable Theme theme) { 5907d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 5917d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return res.getColor(id, theme); 59207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko } else { 5937d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return res.getColor(id); 59407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko } 59507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko } 59607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko 59707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko /** 5987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Returns a color state list associated with a particular resource ID. 5997d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 6007d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @see #getColorStateList(android.content.res.Resources,int,Theme) 6017d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 6027d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public static ColorStateList getColorStateList(Resources res, int id) { 6037d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return getColorStateList(res, id, null); 6047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 6057d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 6067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko /** 6077d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Returns a color state list associated with a particular resource ID. 6087d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * 6097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * <p>In M version, {@link android.content.res.Resources#getColorStateList(int)} was deprecated 6107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * and {@link android.content.res.Resources#getColorStateList(int,Theme)} was newly added. 61107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * 6127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * @see android.content.res.Resources#getColorStateList(int) 61307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko */ 6147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public static ColorStateList getColorStateList(Resources res, int id, @Nullable Theme theme) { 6157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 6167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return res.getColorStateList(id, theme); 61707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko } else { 6187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return res.getColorStateList(id); 6197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 6207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 6217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 6221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 62348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns a localized version of the text resource specified by resourceId. 6241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 62548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public static CharSequence getTextForLocale(Context context, Locale locale, int resourceId) { 62648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (locale.equals(context.getResources().getConfiguration().locale)) { 62748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return context.getText(resourceId); 6281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 62948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Configuration config = new Configuration(context.getResources().getConfiguration()); 63048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho config.setLocale(locale); 63148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return context.createConfigurationContext(config).getText(resourceId); 6321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 6331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 6341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko /** 63548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Returns the internal TV inputs. 6361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 63748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public static List<TvInputInfo> getInternalTvInputs(Context context, boolean tunerInputOnly) { 63848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho List<TvInputInfo> inputs = new ArrayList<>(); 63948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho String contextPackageName = context.getPackageName(); 64048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho for (TvInputInfo input : TvApplication.getSingletons(context).getTvInputManagerHelper() 64148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .getTvInputInfos(true, tunerInputOnly)) { 64248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (contextPackageName.equals(ComponentName.unflattenFromString(input.getId()) 64348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .getPackageName())) { 64448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho inputs.add(input); 64548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 6461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 64748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return inputs; 6481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 6497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 65048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 65148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Checks whether the input is internal or not. 65248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 65348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public static boolean isInternalTvInput(Context context, String inputId) { 65448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return context.getPackageName().equals(ComponentName.unflattenFromString(inputId) 65548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .getPackageName()); 65648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 6573a72b93e554bd22a5c64e71a6956d9604ce05108Youngsang Cho 65848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho /** 65948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho * Shows a toast message to notice that the current feature is a developer feature. 66048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho */ 66148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho public static void showToastMessageForDeveloperFeature(Context context) { 66248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Toast.makeText(context, "This feature is for developer preview.", Toast.LENGTH_SHORT) 66348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .show(); 66407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko } 6653f07ce6c09b77e0c9224a16a4c73c8750ff8a07bYoungsang Cho} 666