• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.data;
18 
19 import android.annotation.TargetApi;
20 import android.content.ContentResolver;
21 import android.content.ContentUris;
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.database.SQLException;
25 import android.graphics.Bitmap;
26 import android.graphics.drawable.BitmapDrawable;
27 import android.graphics.drawable.Drawable;
28 import android.media.tv.TvContract;
29 import android.net.Uri;
30 import android.os.AsyncTask;
31 import android.os.Build;
32 import android.support.annotation.IntDef;
33 import android.support.annotation.MainThread;
34 import android.support.media.tv.ChannelLogoUtils;
35 import android.support.media.tv.PreviewProgram;
36 import android.util.Log;
37 import android.util.Pair;
38 
39 import com.android.tv.R;
40 import com.android.tv.util.PermissionUtils;
41 
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 import java.util.HashMap;
45 import java.util.Map;
46 import java.util.Set;
47 import java.util.concurrent.CopyOnWriteArraySet;
48 
49 /**
50  * Class to manage the preview data.
51  */
52 @TargetApi(Build.VERSION_CODES.O)
53 @MainThread
54 public class PreviewDataManager {
55     private static final String TAG = "PreviewDataManager";
56     // STOPSHIP: set it to false.
57     private static final boolean DEBUG = true;
58 
59     /**
60      * Invalid preview channel ID.
61      */
62     public static final long INVALID_PREVIEW_CHANNEL_ID = -1;
63     @IntDef({TYPE_DEFAULT_PREVIEW_CHANNEL, TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL})
64     @Retention(RetentionPolicy.SOURCE)
65     public @interface PreviewChannelType{}
66 
67     /**
68      * Type of default preview channel
69      */
70     public static final long TYPE_DEFAULT_PREVIEW_CHANNEL = 1;
71     /**
72      * Type of recorded program channel
73      */
74     public static final long TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL = 2;
75 
76     private final Context mContext;
77     private final ContentResolver mContentResolver;
78     private boolean mLoadFinished;
79     private PreviewData mPreviewData = new PreviewData();
80     private final Set<PreviewDataListener> mPreviewDataListeners = new CopyOnWriteArraySet<>();
81 
82     private QueryPreviewDataTask mQueryPreviewTask;
83     private final Map<Long, CreatePreviewChannelTask> mCreatePreviewChannelTasks =
84             new HashMap<>();
85     private final Map<Long, UpdatePreviewProgramTask> mUpdatePreviewProgramTasks = new HashMap<>();
86 
87     private final int mPreviewChannelLogoWidth;
88     private final int mPreviewChannelLogoHeight;
89 
PreviewDataManager(Context context)90     public PreviewDataManager(Context context) {
91         mContext = context.getApplicationContext();
92         mContentResolver = context.getContentResolver();
93         mPreviewChannelLogoWidth = mContext.getResources().getDimensionPixelSize(
94                 R.dimen.preview_channel_logo_width);
95         mPreviewChannelLogoHeight = mContext.getResources().getDimensionPixelSize(
96                 R.dimen.preview_channel_logo_height);
97     }
98 
99     /**
100      * Starts the preview data manager.
101      */
start()102     public void start() {
103         if (mQueryPreviewTask == null) {
104             mQueryPreviewTask = new QueryPreviewDataTask();
105             mQueryPreviewTask.execute();
106         }
107     }
108 
109     /**
110      * Stops the preview data manager.
111      */
stop()112     public void stop() {
113         if (mQueryPreviewTask != null) {
114             mQueryPreviewTask.cancel(true);
115         }
116         for (CreatePreviewChannelTask createPreviewChannelTask
117                 : mCreatePreviewChannelTasks.values()) {
118             createPreviewChannelTask.cancel(true);
119         }
120         for (UpdatePreviewProgramTask updatePreviewProgramTask
121                 : mUpdatePreviewProgramTasks.values()) {
122             updatePreviewProgramTask.cancel(true);
123         }
124 
125         mQueryPreviewTask = null;
126         mCreatePreviewChannelTasks.clear();
127         mUpdatePreviewProgramTasks.clear();
128     }
129 
130     /**
131      * Gets preview channel ID from the preview channel type.
132      */
getPreviewChannelId(long previewChannelType)133     public @PreviewChannelType long getPreviewChannelId(long previewChannelType) {
134         return mPreviewData.getPreviewChannelId(previewChannelType);
135     }
136 
137     /**
138      * Creates default preview channel.
139      */
createDefaultPreviewChannel( OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener)140     public void createDefaultPreviewChannel(
141             OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
142         createPreviewChannel(TYPE_DEFAULT_PREVIEW_CHANNEL, onPreviewChannelCreationResultListener);
143     }
144 
145     /**
146      * Creates a preview channel for specific channel type.
147      */
createPreviewChannel(@reviewChannelType long previewChannelType, OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener)148     public void createPreviewChannel(@PreviewChannelType long previewChannelType,
149             OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
150         CreatePreviewChannelTask currentRunningCreateTask =
151                 mCreatePreviewChannelTasks.get(previewChannelType);
152         if (currentRunningCreateTask == null) {
153             CreatePreviewChannelTask createPreviewChannelTask = new CreatePreviewChannelTask(
154                     previewChannelType);
155             createPreviewChannelTask.addOnPreviewChannelCreationResultListener(
156                     onPreviewChannelCreationResultListener);
157             createPreviewChannelTask.execute();
158             mCreatePreviewChannelTasks.put(previewChannelType, createPreviewChannelTask);
159         } else {
160             currentRunningCreateTask.addOnPreviewChannelCreationResultListener(
161                     onPreviewChannelCreationResultListener);
162         }
163     }
164 
165     /**
166      * Returns {@code true} if the preview data is loaded.
167      */
isLoadFinished()168     public boolean isLoadFinished() {
169         return mLoadFinished;
170     }
171 
172     /**
173      * Adds listener.
174      */
addListener(PreviewDataListener previewDataListener)175     public void addListener(PreviewDataListener previewDataListener) {
176         mPreviewDataListeners.add(previewDataListener);
177     }
178 
179     /**
180      * Removes listener.
181      */
removeListener(PreviewDataListener previewDataListener)182     public void removeListener(PreviewDataListener previewDataListener) {
183         mPreviewDataListeners.remove(previewDataListener);
184     }
185 
186     /**
187      * Updates the preview programs table for a specific preview channel.
188      */
updatePreviewProgramsForChannel(long previewChannelId, Set<PreviewProgramContent> programs, PreviewDataListener previewDataListener)189     public void updatePreviewProgramsForChannel(long previewChannelId,
190             Set<PreviewProgramContent> programs, PreviewDataListener previewDataListener) {
191         UpdatePreviewProgramTask currentRunningUpdateTask =
192                 mUpdatePreviewProgramTasks.get(previewChannelId);
193         if (currentRunningUpdateTask != null
194                 && currentRunningUpdateTask.getPrograms().equals(programs)) {
195             currentRunningUpdateTask.addPreviewDataListener(previewDataListener);
196             return;
197         }
198         UpdatePreviewProgramTask updatePreviewProgramTask =
199                 new UpdatePreviewProgramTask(previewChannelId, programs);
200         updatePreviewProgramTask.addPreviewDataListener(previewDataListener);
201         if (currentRunningUpdateTask != null) {
202             currentRunningUpdateTask.cancel(true);
203             currentRunningUpdateTask.saveStatus();
204             updatePreviewProgramTask.addPreviewDataListeners(
205                     currentRunningUpdateTask.getPreviewDataListeners());
206         }
207         updatePreviewProgramTask.execute();
208         mUpdatePreviewProgramTasks.put(previewChannelId, updatePreviewProgramTask);
209     }
210 
notifyPreviewDataLoadFinished()211     private void notifyPreviewDataLoadFinished() {
212         for (PreviewDataListener l : mPreviewDataListeners) {
213             l.onPreviewDataLoadFinished();
214         }
215     }
216 
217     public interface PreviewDataListener {
218         /**
219          * Called when the preview data is loaded.
220          */
onPreviewDataLoadFinished()221         void onPreviewDataLoadFinished();
222 
223         /**
224          * Called when the preview data is updated.
225          */
onPreviewDataUpdateFinished()226         void onPreviewDataUpdateFinished();
227     }
228 
229     public interface OnPreviewChannelCreationResultListener {
230         /**
231          * Called when the creation of preview channel is finished.
232          * @param createdPreviewChannelId The preview channel ID if created successfully,
233          *        otherwise it's {@value #INVALID_PREVIEW_CHANNEL_ID}.
234          */
onPreviewChannelCreationResult(long createdPreviewChannelId)235         void onPreviewChannelCreationResult(long createdPreviewChannelId);
236     }
237 
238     private final class QueryPreviewDataTask extends AsyncTask<Void, Void, PreviewData> {
239         private final String PARAM_PREVIEW = "preview";
240         private final String mChannelSelection = TvContract.Channels.COLUMN_PACKAGE_NAME + "=?";
241 
242         @Override
doInBackground(Void... voids)243         protected PreviewData doInBackground(Void... voids) {
244             // Query preview channels and programs.
245             if (DEBUG) Log.d(TAG, "QueryPreviewDataTask.doInBackground");
246             PreviewData previewData = new PreviewData();
247             try {
248                 Uri previewChannelsUri =
249                         PreviewDataUtils.addQueryParamToUri(
250                                 TvContract.Channels.CONTENT_URI,
251                                 new Pair<>(PARAM_PREVIEW, String.valueOf(true)));
252                 String packageName = mContext.getPackageName();
253                 if (PermissionUtils.hasAccessAllEpg(mContext)) {
254                     try (Cursor cursor =
255                             mContentResolver.query(
256                                     previewChannelsUri,
257                                     android.support.media.tv.Channel.PROJECTION,
258                                     mChannelSelection,
259                                     new String[] {packageName},
260                                     null)) {
261                         if (cursor != null) {
262                             while (cursor.moveToNext()) {
263                                 android.support.media.tv.Channel previewChannel =
264                                         android.support.media.tv.Channel.fromCursor(cursor);
265                                 Long previewChannelType = previewChannel.getInternalProviderFlag1();
266                                 if (previewChannelType != null) {
267                                     previewData.addPreviewChannelId(
268                                             previewChannelType, previewChannel.getId());
269                                 }
270                             }
271                         }
272                     }
273                 } else {
274                     try (Cursor cursor =
275                             mContentResolver.query(
276                                     previewChannelsUri,
277                                     android.support.media.tv.Channel.PROJECTION,
278                                     null,
279                                     null,
280                                     null)) {
281                         if (cursor != null) {
282                             while (cursor.moveToNext()) {
283                                 android.support.media.tv.Channel previewChannel =
284                                         android.support.media.tv.Channel.fromCursor(cursor);
285                                 Long previewChannelType = previewChannel.getInternalProviderFlag1();
286                                 if (previewChannel.getPackageName() == packageName
287                                         && previewChannelType != null) {
288                                     previewData.addPreviewChannelId(
289                                             previewChannelType, previewChannel.getId());
290                                 }
291                             }
292                         }
293                     }
294                 }
295 
296                 for (long previewChannelId : previewData.getAllPreviewChannelIds().values()) {
297                     Uri previewProgramsUriForPreviewChannel =
298                             TvContract.buildPreviewProgramsUriForChannel(previewChannelId);
299                     try (Cursor previewProgramCursor =
300                             mContentResolver.query(
301                                     previewProgramsUriForPreviewChannel,
302                                     PreviewProgram.PROJECTION,
303                                     null,
304                                     null,
305                                     null)) {
306                         if (previewProgramCursor != null) {
307                             while (previewProgramCursor.moveToNext()) {
308                                 PreviewProgram previewProgram =
309                                         PreviewProgram.fromCursor(previewProgramCursor);
310                                 previewData.addPreviewProgram(previewProgram);
311                             }
312                         }
313                     }
314                 }
315             } catch (SQLException e) {
316                 Log.w(TAG, "Unable to get preview data", e);
317             }
318             return previewData;
319         }
320 
321         @Override
onPostExecute(PreviewData result)322         protected void onPostExecute(PreviewData result) {
323             super.onPostExecute(result);
324             if (mQueryPreviewTask == this) {
325                 mQueryPreviewTask = null;
326                 mPreviewData = new PreviewData(result);
327                 mLoadFinished = true;
328                 notifyPreviewDataLoadFinished();
329             }
330         }
331     }
332 
333     private final class CreatePreviewChannelTask extends AsyncTask<Void, Void, Long> {
334         private final long mPreviewChannelType;
335         private Set<OnPreviewChannelCreationResultListener>
336                 mOnPreviewChannelCreationResultListeners = new CopyOnWriteArraySet<>();
337 
CreatePreviewChannelTask(long previewChannelType)338         public CreatePreviewChannelTask(long previewChannelType) {
339             mPreviewChannelType = previewChannelType;
340         }
341 
addOnPreviewChannelCreationResultListener( OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener)342         public void addOnPreviewChannelCreationResultListener(
343                 OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
344             if (onPreviewChannelCreationResultListener != null) {
345                 mOnPreviewChannelCreationResultListeners.add(
346                         onPreviewChannelCreationResultListener);
347             }
348         }
349 
350         @Override
doInBackground(Void... params)351         protected Long doInBackground(Void... params) {
352             if (DEBUG) Log.d(TAG, "CreatePreviewChannelTask.doInBackground");
353             long previewChannelId;
354             try {
355                 Uri channelUri = mContentResolver.insert(TvContract.Channels.CONTENT_URI,
356                         PreviewDataUtils.createPreviewChannel(mContext, mPreviewChannelType)
357                                 .toContentValues());
358                 if (channelUri != null) {
359                     previewChannelId = ContentUris.parseId(channelUri);
360                 } else {
361                     Log.e(TAG, "Fail to insert preview channel");
362                     return INVALID_PREVIEW_CHANNEL_ID;
363                 }
364             } catch (UnsupportedOperationException | NumberFormatException e) {
365                 Log.e(TAG, "Fail to get channel ID");
366                 return INVALID_PREVIEW_CHANNEL_ID;
367             }
368             Drawable appIcon = mContext.getApplicationInfo().loadIcon(mContext.getPackageManager());
369             if (appIcon != null && appIcon instanceof BitmapDrawable) {
370                 ChannelLogoUtils.storeChannelLogo(mContext, previewChannelId,
371                         Bitmap.createScaledBitmap(((BitmapDrawable) appIcon).getBitmap(),
372                                 mPreviewChannelLogoWidth, mPreviewChannelLogoHeight, false));
373             }
374             return previewChannelId;
375         }
376 
377         @Override
onPostExecute(Long result)378         protected void onPostExecute(Long result) {
379             super.onPostExecute(result);
380             if (result != INVALID_PREVIEW_CHANNEL_ID) {
381                 mPreviewData.addPreviewChannelId(mPreviewChannelType, result);
382             }
383             for (OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener
384                     : mOnPreviewChannelCreationResultListeners) {
385                 onPreviewChannelCreationResultListener.onPreviewChannelCreationResult(result);
386             }
387             mCreatePreviewChannelTasks.remove(mPreviewChannelType);
388         }
389     }
390 
391     /**
392      * Updates the whole data which belongs to the package in preview programs table for a
393      * specific preview channel with a set of {@link PreviewProgramContent}.
394      */
395     private final class UpdatePreviewProgramTask extends AsyncTask<Void, Void, Void> {
396         private long mPreviewChannelId;
397         private Set<PreviewProgramContent> mPrograms;
398         private Map<Long, Long> mCurrentProgramId2PreviewProgramId;
399         private Set<PreviewDataListener> mPreviewDataListeners = new CopyOnWriteArraySet<>();
400 
UpdatePreviewProgramTask(long previewChannelId, Set<PreviewProgramContent> programs)401         public UpdatePreviewProgramTask(long previewChannelId,
402                 Set<PreviewProgramContent> programs) {
403             mPreviewChannelId = previewChannelId;
404             mPrograms = programs;
405             if (mPreviewData.getPreviewProgramIds(previewChannelId) == null) {
406                 mCurrentProgramId2PreviewProgramId = new HashMap<>();
407             } else {
408                 mCurrentProgramId2PreviewProgramId = new HashMap<>(
409                         mPreviewData.getPreviewProgramIds(previewChannelId));
410             }
411         }
412 
addPreviewDataListener(PreviewDataListener previewDataListener)413         public void addPreviewDataListener(PreviewDataListener previewDataListener) {
414             if (previewDataListener != null) {
415                 mPreviewDataListeners.add(previewDataListener);
416             }
417         }
418 
addPreviewDataListeners(Set<PreviewDataListener> previewDataListeners)419         public void addPreviewDataListeners(Set<PreviewDataListener> previewDataListeners) {
420             if (previewDataListeners != null) {
421                 mPreviewDataListeners.addAll(previewDataListeners);
422             }
423         }
424 
getPrograms()425         public Set<PreviewProgramContent> getPrograms() {
426             return mPrograms;
427         }
428 
getPreviewDataListeners()429         public Set<PreviewDataListener> getPreviewDataListeners() {
430             return mPreviewDataListeners;
431         }
432 
433         @Override
doInBackground(Void... params)434         protected Void doInBackground(Void... params) {
435             if (DEBUG) Log.d(TAG, "UpdatePreviewProgamTask.doInBackground");
436             Map<Long, Long> uncheckedPrograms = new HashMap<>(mCurrentProgramId2PreviewProgramId);
437             for (PreviewProgramContent program : mPrograms) {
438                 if (isCancelled()) {
439                     return null;
440                 }
441                 Long existingPreviewProgramId = uncheckedPrograms.remove(program.getId());
442                 if (existingPreviewProgramId != null) {
443                     if (DEBUG) Log.d(TAG, "Preview program " + existingPreviewProgramId + " " +
444                             "already exists for program " + program.getId());
445                     continue;
446                 }
447                 try {
448                     Uri programUri = mContentResolver.insert(TvContract.PreviewPrograms.CONTENT_URI,
449                             PreviewDataUtils.createPreviewProgramFromContent(program)
450                                     .toContentValues());
451                     if (programUri != null) {
452                         long previewProgramId = ContentUris.parseId(programUri);
453                         mCurrentProgramId2PreviewProgramId.put(program.getId(), previewProgramId);
454                         if (DEBUG) Log.d(TAG, "Add new preview program " + previewProgramId);
455                     } else {
456                         Log.e(TAG, "Fail to insert preview program");
457                     }
458                 } catch (Exception e) {
459                     Log.e(TAG, "Fail to get preview program ID");
460                 }
461             }
462 
463             for (Long key : uncheckedPrograms.keySet()) {
464                 if (isCancelled()) {
465                     return null;
466                 }
467                 try {
468                     if (DEBUG) Log.d(TAG, "Remove preview program " + uncheckedPrograms.get(key));
469                     mContentResolver.delete(TvContract.buildPreviewProgramUri(
470                             uncheckedPrograms.get(key)), null, null);
471                     mCurrentProgramId2PreviewProgramId.remove(key);
472                 } catch (Exception e) {
473                     Log.e(TAG, "Fail to remove preview program " + uncheckedPrograms.get(key));
474                 }
475             }
476             return null;
477         }
478 
479         @Override
onPostExecute(Void result)480         protected void onPostExecute(Void result) {
481             super.onPostExecute(result);
482             mPreviewData.setPreviewProgramIds(
483                     mPreviewChannelId, mCurrentProgramId2PreviewProgramId);
484             mUpdatePreviewProgramTasks.remove(mPreviewChannelId);
485             for (PreviewDataListener previewDataListener : mPreviewDataListeners) {
486                 previewDataListener.onPreviewDataUpdateFinished();
487             }
488         }
489 
saveStatus()490         public void saveStatus() {
491             mPreviewData.setPreviewProgramIds(
492                     mPreviewChannelId, mCurrentProgramId2PreviewProgramId);
493         }
494     }
495 
496     /**
497      * Class to store the query result of preview data.
498      */
499     private static final class PreviewData {
500         private Map<Long, Long> mPreviewChannelType2Id = new HashMap<>();
501         private Map<Long, Map<Long, Long>> mProgramId2PreviewProgramId = new HashMap<>();
502 
PreviewData()503         PreviewData() {
504             mPreviewChannelType2Id = new HashMap<>();
505             mProgramId2PreviewProgramId = new HashMap<>();
506         }
507 
PreviewData(PreviewData previewData)508         PreviewData(PreviewData previewData) {
509             mPreviewChannelType2Id = new HashMap<>(previewData.mPreviewChannelType2Id);
510             mProgramId2PreviewProgramId = new HashMap<>(previewData.mProgramId2PreviewProgramId);
511         }
512 
addPreviewProgram(PreviewProgram previewProgram)513         public void addPreviewProgram(PreviewProgram previewProgram) {
514             long previewChannelId = previewProgram.getChannelId();
515             Map<Long, Long> programId2PreviewProgram =
516                     mProgramId2PreviewProgramId.get(previewChannelId);
517             if (programId2PreviewProgram == null) {
518                 programId2PreviewProgram = new HashMap<>();
519             }
520             mProgramId2PreviewProgramId.put(previewChannelId, programId2PreviewProgram);
521             if (previewProgram.getInternalProviderId() != null) {
522                 programId2PreviewProgram.put(
523                         Long.parseLong(previewProgram.getInternalProviderId()),
524                         previewProgram.getId());
525             }
526         }
527 
getPreviewChannelId(long previewChannelType)528         public @PreviewChannelType long getPreviewChannelId(long previewChannelType) {
529             Long result = mPreviewChannelType2Id.get(previewChannelType);
530             return result == null ? INVALID_PREVIEW_CHANNEL_ID : result;
531         }
532 
getAllPreviewChannelIds()533         public Map<Long, Long> getAllPreviewChannelIds() {
534             return mPreviewChannelType2Id;
535         }
536 
addPreviewChannelId(long previewChannelType, long previewChannelId)537         public void addPreviewChannelId(long previewChannelType, long previewChannelId) {
538             mPreviewChannelType2Id.put(previewChannelType, previewChannelId);
539         }
540 
removePreviewChannelId(long previewChannelType)541         public void removePreviewChannelId(long previewChannelType) {
542             mPreviewChannelType2Id.remove(previewChannelType);
543         }
544 
removePreviewChannel(long previewChannelId)545         public void removePreviewChannel(long previewChannelId) {
546             removePreviewChannelId(previewChannelId);
547             removePreviewProgramIds(previewChannelId);
548         }
549 
getPreviewProgramIds(long previewChannelId)550         public Map<Long, Long> getPreviewProgramIds(long previewChannelId) {
551             return mProgramId2PreviewProgramId.get(previewChannelId);
552         }
553 
getAllPreviewProgramIds()554         public Map<Long, Map<Long, Long>> getAllPreviewProgramIds() {
555             return mProgramId2PreviewProgramId;
556         }
557 
setPreviewProgramIds( long previewChannelId, Map<Long, Long> programId2PreviewProgramId)558         public void setPreviewProgramIds(
559                 long previewChannelId, Map<Long, Long> programId2PreviewProgramId) {
560             mProgramId2PreviewProgramId.put(previewChannelId, programId2PreviewProgramId);
561         }
562 
removePreviewProgramIds(long previewChannelId)563         public void removePreviewProgramIds(long previewChannelId) {
564             mProgramId2PreviewProgramId.remove(previewChannelId);
565         }
566     }
567 
568     /**
569      * A utils class for preview data.
570      */
571     public final static class PreviewDataUtils {
572         /**
573          * Creates a preview channel.
574          */
createPreviewChannel( Context context, @PreviewChannelType long previewChannelType)575         public static android.support.media.tv.Channel createPreviewChannel(
576                 Context context, @PreviewChannelType long previewChannelType) {
577             if (previewChannelType == TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL) {
578                 return createRecordedProgramPreviewChannel(context, previewChannelType);
579             }
580             return createDefaultPreviewChannel(context, previewChannelType);
581         }
582 
createDefaultPreviewChannel( Context context, @PreviewChannelType long previewChannelType)583         private static android.support.media.tv.Channel createDefaultPreviewChannel(
584                 Context context, @PreviewChannelType long previewChannelType) {
585             android.support.media.tv.Channel.Builder builder =
586                     new android.support.media.tv.Channel.Builder();
587             CharSequence appLabel =
588                     context.getApplicationInfo().loadLabel(context.getPackageManager());
589             CharSequence appDescription =
590                     context.getApplicationInfo().loadDescription(context.getPackageManager());
591             builder.setType(TvContract.Channels.TYPE_PREVIEW)
592                     .setDisplayName(appLabel == null ? null : appLabel.toString())
593                     .setDescription(appDescription == null ?  null : appDescription.toString())
594                     .setAppLinkIntentUri(TvContract.Channels.CONTENT_URI)
595                     .setInternalProviderFlag1(previewChannelType);
596             return builder.build();
597         }
598 
createRecordedProgramPreviewChannel( Context context, @PreviewChannelType long previewChannelType)599         private static android.support.media.tv.Channel createRecordedProgramPreviewChannel(
600                 Context context, @PreviewChannelType long previewChannelType) {
601             android.support.media.tv.Channel.Builder builder =
602                     new android.support.media.tv.Channel.Builder();
603             builder.setType(TvContract.Channels.TYPE_PREVIEW)
604                     .setDisplayName(context.getResources().getString(
605                             R.string.recorded_programs_preview_channel))
606                     .setAppLinkIntentUri(TvContract.Channels.CONTENT_URI)
607                     .setInternalProviderFlag1(previewChannelType);
608             return builder.build();
609         }
610 
611         /**
612          * Creates a preview program.
613          */
createPreviewProgramFromContent( PreviewProgramContent program)614         public static PreviewProgram createPreviewProgramFromContent(
615                 PreviewProgramContent program) {
616             PreviewProgram.Builder builder = new PreviewProgram.Builder();
617             builder.setChannelId(program.getPreviewChannelId())
618                     .setType(program.getType())
619                     .setLive(program.getLive())
620                     .setTitle(program.getTitle())
621                     .setDescription(program.getDescription())
622                     .setPosterArtUri(program.getPosterArtUri())
623                     .setIntentUri(program.getIntentUri())
624                     .setPreviewVideoUri(program.getPreviewVideoUri())
625                     .setInternalProviderId(Long.toString(program.getId()));
626             return builder.build();
627         }
628 
629         /**
630          * Appends query parameters to a Uri.
631          */
addQueryParamToUri(Uri uri, Pair<String, String> param)632         public static Uri addQueryParamToUri(Uri uri, Pair<String, String> param) {
633             return uri.buildUpon().appendQueryParameter(param.first, param.second).build();
634         }
635     }
636 }
637