1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/* 2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project 3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License. 6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at 7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software 11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and 14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License. 15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv.util; 18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 19816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.ComponentName; 20816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Context; 21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Intent; 22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.SharedPreferences; 23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContract; 24816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputInfo; 25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvInputManager; 26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.os.Build; 27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.preference.PreferenceManager; 28ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.Nullable; 29ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.annotation.UiThread; 3048dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.text.TextUtils; 3148dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport android.util.ArraySet; 32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log; 33816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 341abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.tv.ApplicationSingletons; 357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.TvApplication; 3648dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.android.tv.common.SoftPreconditions; 377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.Channel; 387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.data.ChannelDataManager; 397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 40ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport java.util.Collections; 41816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.HashSet; 42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.Set; 43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 44816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/** 45816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * A utility class related to input setup. 46816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 47816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopublic class SetupUtils { 48816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String TAG = "SetupUtils"; 49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final boolean DEBUG = false; 50816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 51816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // Known inputs are inputs which are shown in SetupView before. When a new input is installed, 52816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // the input will not be included in "PREF_KEY_KNOWN_INPUTS". 53816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_KNOWN_INPUTS = "known_inputs"; 547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // Set up inputs are inputs whose setup activity has been launched and finished successfully. 55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_SET_UP_INPUTS = "set_up_inputs"; 56ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko // Recognized inputs means that the user already knows the inputs are installed. 57ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko private static final String PREF_KEY_RECOGNIZED_INPUTS = "recognized_inputs"; 58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static final String PREF_KEY_IS_FIRST_TUNE = "is_first_tune"; 59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private static SetupUtils sSetupUtils; 60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 617d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private final TvApplication mTvApplication; 62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final SharedPreferences mSharedPreferences; 63816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final Set<String> mKnownInputs; 64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private final Set<String> mSetUpInputs; 65ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko private final Set<String> mRecognizedInputs; 66816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko private boolean mIsFirstTune; 671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private final String mUsbTunerInputId; 68816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 697d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private SetupUtils(TvApplication tvApplication) { 707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mTvApplication = tvApplication; 717d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(tvApplication); 7248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mSetUpInputs = new ArraySet<>(); 73ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSetUpInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_SET_UP_INPUTS, 74ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Collections.<String>emptySet())); 7548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mKnownInputs = new ArraySet<>(); 76ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mKnownInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_KNOWN_INPUTS, 77ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Collections.<String>emptySet())); 7848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mRecognizedInputs = new ArraySet<>(); 79ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mRecognizedInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_RECOGNIZED_INPUTS, 80ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mKnownInputs)); 81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mIsFirstTune = mSharedPreferences.getBoolean(PREF_KEY_IS_FIRST_TUNE, true); 821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mUsbTunerInputId = TvContract.buildInputId(new ComponentName(tvApplication, 831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko com.android.usbtuner.tvinput.UsbTunerTvInputService.class)); 84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 85816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 86816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 87816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Gets an instance of {@link SetupUtils}. 88816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 89816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static SetupUtils getInstance(Context context) { 90816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (sSetupUtils != null) { 91816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return sSetupUtils; 92816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 937d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko sSetupUtils = new SetupUtils((TvApplication) context.getApplicationContext()); 94816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return sSetupUtils; 95816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko /** 987d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Additional work after the setup of TV input. 997d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko */ 100ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public void onTvInputSetupFinished(final String inputId, 101ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko @Nullable final Runnable postRunnable) { 1027d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // When TIS adds several channels, ChannelDataManager.Listener.onChannelList 1037d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // Updated() can be called several times. In this case, it is hard to detect 1047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // which one is the last callback. To reduce error prune, we update channel 1057d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko // list again and make all channels of {@code inputId} browsable. 1067d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko onSetupDone(inputId); 1077d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko final ChannelDataManager manager = mTvApplication.getChannelDataManager(); 1087d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (!manager.isDbLoadFinished()) { 1097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.addListener(new ChannelDataManager.Listener() { 1107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 1117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void onLoadFinished() { 1127d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.removeListener(this); 1137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko updateChannelBrowsable(mTvApplication, inputId, postRunnable); 1147d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1167d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 1177d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void onChannelListUpdated() { } 1187d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1197d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 1207d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void onChannelBrowsableChanged() { } 1217d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko }); 1227d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } else { 1237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko updateChannelBrowsable(mTvApplication, inputId, postRunnable); 1247d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1257d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1267d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 1277d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko private static void updateChannelBrowsable(Context context, final String inputId, 1287d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko final Runnable postRunnable) { 1291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko ApplicationSingletons appSingletons = TvApplication.getSingletons(context); 1301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko final ChannelDataManager manager = appSingletons.getChannelDataManager(); 1317d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.updateChannels(new Runnable() { 1327d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko @Override 1337d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void run() { 1347d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko boolean browsableChanged = false; 1357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko for (Channel channel : manager.getChannelList()) { 1367d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (channel.getInputId().equals(inputId)) { 1377d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (!channel.isBrowsable()) { 1387d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.updateBrowsable(channel.getId(), true, true); 1397d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko browsableChanged = true; 1407d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1427d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1437d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (browsableChanged) { 1447d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.notifyChannelBrowsableChanged(); 1457d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko manager.applyUpdatedValuesToDb(); 1467d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1477d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (postRunnable != null) { 1487d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko postRunnable.run(); 1497d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1507d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1517d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko }); 1527d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 1537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko 154ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 155ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Marks the channels in newly installed inputs browsable. 156ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 157ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko @UiThread 158ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public void markNewChannelsBrowsable() { 159ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Set<String> newInputsWithChannels = new HashSet<>(); 160ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko TvInputManagerHelper tvInputManagerHelper = mTvApplication.getTvInputManagerHelper(); 161ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko ChannelDataManager channelDataManager = mTvApplication.getChannelDataManager(); 162ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko SoftPreconditions.checkState(channelDataManager.isDbLoadFinished()); 163ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko for (TvInputInfo input : tvInputManagerHelper.getTvInputInfos(true, true)) { 164ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko String inputId = input.getId(); 165ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!isSetupDone(inputId) && channelDataManager.getChannelCountForInput(inputId) > 0) { 166ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko onSetupDone(inputId); 167ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko newInputsWithChannels.add(inputId); 168ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (DEBUG) { 169ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Log.d(TAG, "New input " + inputId + " has " 170ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko + channelDataManager.getChannelCountForInput(inputId) 171ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko + " channels"); 172ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 173ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 174ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 175ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!newInputsWithChannels.isEmpty()) { 176ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko for (Channel channel : channelDataManager.getChannelList()) { 177ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (newInputsWithChannels.contains(channel.getInputId())) { 178ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko channelDataManager.updateBrowsable(channel.getId(), true); 179ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 180ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 181ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko channelDataManager.applyUpdatedValuesToDb(); 182ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 183ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 184ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean isFirstTune() { 186816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return mIsFirstTune; 187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns true, if the input with {@code inputId} is newly installed. 191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean isNewInput(String inputId) { 193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return !mKnownInputs.contains(inputId); 194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Marks an input with {@code inputId} as a known input. Once it is marked, {@link #isNewInput} 198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * will return false. 199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void markAsKnownInput(String inputId) { 201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mKnownInputs.add(inputId); 202ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mRecognizedInputs.add(inputId); 203ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSharedPreferences.edit().putStringSet(PREF_KEY_KNOWN_INPUTS, mKnownInputs) 204ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .putStringSet(PREF_KEY_RECOGNIZED_INPUTS, mRecognizedInputs).apply(); 205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 206816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 2087d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Returns {@code true}, if {@code inputId}'s setup has been done before. 209816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 2107d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public boolean isSetupDone(String inputId) { 2117d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko boolean done = mSetUpInputs.contains(inputId); 212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) { 2137d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.d(TAG, "isSetupDone: (input=" + inputId + ", result= " + done + ")"); 214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 2157d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko return done; 216816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 217816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 218816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 219816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Returns true, if there is any newly installed input. 220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public boolean hasNewInput(TvInputManagerHelper inputManager) { 222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (TvInputInfo input : inputManager.getTvInputInfos(true, true)) { 223816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (isNewInput(input.getId())) { 224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return true; 225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 226816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 227816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return false; 228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 231ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Checks whether the given input is already recognized by the user or not. 232ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 233ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko private boolean isRecognizedInput(String inputId) { 234ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko return mRecognizedInputs.contains(inputId); 235ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 236ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 237ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 238ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Marks all the inputs as recognized inputs. Once it is marked, {@link #isRecognizedInput} will 239ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * return {@code true}. 240ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 241ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public void markAllInputsRecognized(TvInputManagerHelper inputManager) { 242ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko for (TvInputInfo input : inputManager.getTvInputInfos(true, true)) { 243ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mRecognizedInputs.add(input.getId()); 244ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 245ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSharedPreferences.edit().putStringSet(PREF_KEY_RECOGNIZED_INPUTS, mRecognizedInputs) 246ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .apply(); 247ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 248ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 249ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 250ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Checks whether there are any unrecognized inputs. 251ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */ 252ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko public boolean hasUnrecognizedInput(TvInputManagerHelper inputManager) { 253ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko for (TvInputInfo input : inputManager.getTvInputInfos(true, true)) { 254ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!isRecognizedInput(input.getId())) { 255ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko return true; 256ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 257ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 258ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko return false; 259ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 260ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko 261ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko /** 262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Grants permission for writing EPG data to all verified packages. 263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 264816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param context The Context used for granting permission. 265816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static void grantEpgPermissionToSetUpPackages(Context context) { 26748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 26848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // Can't grant permission. 26948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho return; 27048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 27148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 27248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho // Find all already-verified packages. 27348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho Set<String> setUpPackages = new HashSet<>(); 27448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 27548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho for (String input : sp.getStringSet(PREF_KEY_SET_UP_INPUTS, Collections.EMPTY_SET)) { 27648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (!TextUtils.isEmpty(input)) { 27748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho ComponentName componentName = ComponentName.unflattenFromString(input); 27848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho if (componentName != null) { 27948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho setUpPackages.add(componentName.getPackageName()); 2803a72b93e554bd22a5c64e71a6956d9604ce05108Youngsang Cho } 281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 282369b6a409204a9b2a95f7ba575d7c3b7bdc94ab7Youngsang Cho } 28348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho 28448dadb49248271b01997862e1335912a4f2e189fYoungsang Cho for (String packageName : setUpPackages) { 28548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho grantEpgPermission(context, packageName); 28648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho } 287816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 290816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Grants permission for writing EPG data to a given package. 291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * 292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param context The Context used for granting permission. 293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * @param packageName The name of the package to give permission. 294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 295816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public static void grantEpgPermission(Context context, String packageName) { 296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko // TvProvider allows granting of Uri permissions starting from MNC. 2977d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 298816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (DEBUG) { 299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.d(TAG, "grantEpgPermission(context=" + context + ", packageName=" + packageName 300816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko + ")"); 301816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 302816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko try { 303816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko int modeFlags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION 304816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; 305816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko context.grantUriPermission(packageName, TvContract.Channels.CONTENT_URI, modeFlags); 306816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko context.grantUriPermission(packageName, TvContract.Programs.CONTENT_URI, modeFlags); 307816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } catch (SecurityException e) { 308816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko Log.e(TAG, "Either TvProvider does not allow granting of Uri permissions or the app" 3097d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko + " does not have permission.", e); 310816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 311816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 312816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 313816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 314816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 315816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Called when Live channels app is launched. Once it is called, {@link 316816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * #isFirstTune} will return false. 317816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 318816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onTuned() { 319816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!mIsFirstTune) { 320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko return; 321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 322816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mIsFirstTune = false; 323816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mSharedPreferences.edit().putBoolean(PREF_KEY_IS_FIRST_TUNE, false).apply(); 324816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 325816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 326816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Called when input list is changed. It mainly handles input removals. 328816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 329816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko public void onInputListUpdated(TvInputManager manager) { 330ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko // mRecognizedInputs > mKnownInputs > mSetUpInputs. 331ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Set<String> removedInputList = new HashSet<>(mRecognizedInputs); 332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (TvInputInfo input : manager.getTvInputList()) { 333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko removedInputList.remove(input.getId()); 334816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 3351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // A USB tuner device can be temporarily unplugged. We do not remove the USB tuner input 3361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // from the known inputs so that the input won't appear as a new input whenever the user 3371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // plugs in the USB tuner device again. 3381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko removedInputList.remove(mUsbTunerInputId); 339816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 340816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko if (!removedInputList.isEmpty()) { 341816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko for (String input : removedInputList) { 342ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mRecognizedInputs.remove(input); 343816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mSetUpInputs.remove(input); 344816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko mKnownInputs.remove(input); 345816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 346ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSharedPreferences.edit().putStringSet(PREF_KEY_SET_UP_INPUTS, mSetUpInputs) 347ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .putStringSet(PREF_KEY_KNOWN_INPUTS, mKnownInputs) 34848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho .putStringSet(PREF_KEY_RECOGNIZED_INPUTS, mRecognizedInputs).apply(); 349816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 350816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 351816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko 352816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko /** 3537d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Called when an setup is done. Once it is called, {@link #isSetupDone} returns {@code true} 3547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * for {@code inputId}. 355816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */ 3567d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko public void onSetupDone(String inputId) { 3571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko SoftPreconditions.checkState(inputId != null); 3587d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (DEBUG) Log.d(TAG, "onSetupDone: input=" + inputId); 359ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!mRecognizedInputs.contains(inputId)) { 360ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko Log.i(TAG, "An unrecognized input's setup has been done. inputId=" + inputId); 361ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mRecognizedInputs.add(inputId); 36248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho mSharedPreferences.edit().putStringSet(PREF_KEY_RECOGNIZED_INPUTS, mRecognizedInputs) 363ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko .apply(); 364ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 3657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko if (!mKnownInputs.contains(inputId)) { 3667d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko Log.i(TAG, "An unknown input's setup has been done. inputId=" + inputId); 3677d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko mKnownInputs.add(inputId); 368ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSharedPreferences.edit().putStringSet(PREF_KEY_KNOWN_INPUTS, mKnownInputs).apply(); 369ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko } 370ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko if (!mSetUpInputs.contains(inputId)) { 371ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSetUpInputs.add(inputId); 372ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko mSharedPreferences.edit().putStringSet(PREF_KEY_SET_UP_INPUTS, mSetUpInputs).apply(); 3737d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko } 374816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko } 375816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko} 376