• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.dvr.ui.list;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.media.tv.TvContract.Programs;
23 import android.net.Uri;
24 import android.os.Build;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.support.v17.leanback.widget.ClassPresenterSelector;
29 import android.transition.Fade;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import com.android.tv.R;
34 import com.android.tv.TvSingletons;
35 import com.android.tv.data.ChannelDataManager;
36 import com.android.tv.data.Program;
37 import com.android.tv.dvr.DvrDataManager;
38 import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
39 import com.android.tv.dvr.data.SeriesRecording;
40 import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
41 import com.android.tv.dvr.ui.BigArguments;
42 import java.util.Collections;
43 import java.util.List;
44 
45 /** A fragment to show the list of series schedule recordings. */
46 @TargetApi(Build.VERSION_CODES.N)
47 public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
48     /**
49      * The key for series recording whose scheduled recording list will be displayed. Type: {@link
50      * SeriesRecording}
51      */
52     public static final String SERIES_SCHEDULES_KEY_SERIES_RECORDING =
53             "series_schedules_key_series_recording";
54     /**
55      * The key for programs which belong to the series recording whose scheduled recording list will
56      * be displayed. Type: List<{@link Program}>
57      */
58     public static final String SERIES_SCHEDULES_KEY_SERIES_PROGRAMS =
59             "series_schedules_key_series_programs";
60 
61     private ChannelDataManager mChannelDataManager;
62     private DvrDataManager mDvrDataManager;
63     private SeriesRecording mSeriesRecording;
64     private List<Program> mPrograms;
65     private EpisodicProgramLoadTask mProgramLoadTask;
66 
67     private final SeriesRecordingListener mSeriesRecordingListener =
68             new SeriesRecordingListener() {
69                 @Override
70                 public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {}
71 
72                 @Override
73                 public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
74                     for (SeriesRecording r : seriesRecordings) {
75                         if (r.getId() == mSeriesRecording.getId()) {
76                             getActivity().finish();
77                             return;
78                         }
79                     }
80                 }
81 
82                 @Override
83                 public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
84                     for (SeriesRecording r : seriesRecordings) {
85                         if (r.getId() == mSeriesRecording.getId()
86                                 && getRowsAdapter() instanceof SeriesScheduleRowAdapter) {
87                             ((SeriesScheduleRowAdapter) getRowsAdapter())
88                                     .onSeriesRecordingUpdated(r);
89                             mSeriesRecording = r;
90                             updateEmptyMessage();
91                             return;
92                         }
93                     }
94                 }
95             };
96 
97     private final Handler mHandler = new Handler(Looper.getMainLooper());
98     private final ContentObserver mContentObserver =
99             new ContentObserver(mHandler) {
100                 @Override
101                 public void onChange(boolean selfChange, Uri uri) {
102                     super.onChange(selfChange, uri);
103                     executeProgramLoadingTask();
104                 }
105             };
106 
107     private final ChannelDataManager.Listener mChannelListener =
108             new ChannelDataManager.Listener() {
109                 @Override
110                 public void onLoadFinished() {}
111 
112                 @Override
113                 public void onChannelListUpdated() {
114                     executeProgramLoadingTask();
115                 }
116 
117                 @Override
118                 public void onChannelBrowsableChanged() {}
119             };
120 
DvrSeriesSchedulesFragment()121     public DvrSeriesSchedulesFragment() {
122         setEnterTransition(new Fade(Fade.IN));
123     }
124 
125     @Override
onAttach(Context context)126     public void onAttach(Context context) {
127         super.onAttach(context);
128         Bundle args = getArguments();
129         if (args != null) {
130             mSeriesRecording = args.getParcelable(SERIES_SCHEDULES_KEY_SERIES_RECORDING);
131             mPrograms =
132                     (List<Program>) BigArguments.getArgument(SERIES_SCHEDULES_KEY_SERIES_PROGRAMS);
133             BigArguments.reset();
134         }
135         if (args == null || mPrograms == null) {
136             getActivity().finish();
137         }
138     }
139 
140     @Override
onCreate(Bundle savedInstanceState)141     public void onCreate(Bundle savedInstanceState) {
142         super.onCreate(savedInstanceState);
143         TvSingletons singletons = TvSingletons.getSingletons(getContext());
144         mChannelDataManager = singletons.getChannelDataManager();
145         mChannelDataManager.addListener(mChannelListener);
146         mDvrDataManager = singletons.getDvrDataManager();
147         mDvrDataManager.addSeriesRecordingListener(mSeriesRecordingListener);
148         getContext()
149                 .getContentResolver()
150                 .registerContentObserver(Programs.CONTENT_URI, true, mContentObserver);
151     }
152 
153     @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)154     public View onCreateView(
155             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
156         onProgramsUpdated();
157         return super.onCreateView(inflater, container, savedInstanceState);
158     }
159 
onProgramsUpdated()160     private void onProgramsUpdated() {
161         ((SeriesScheduleRowAdapter) getRowsAdapter()).setPrograms(mPrograms);
162         updateEmptyMessage();
163     }
164 
updateEmptyMessage()165     private void updateEmptyMessage() {
166         if (mPrograms == null || mPrograms.isEmpty()) {
167             if (mSeriesRecording.getState() == SeriesRecording.STATE_SERIES_STOPPED) {
168                 showEmptyMessage(R.string.dvr_series_schedules_stopped_empty_state);
169             } else {
170                 showEmptyMessage(R.string.dvr_series_schedules_empty_state);
171             }
172         } else {
173             hideEmptyMessage();
174         }
175     }
176 
177     @Override
onDestroy()178     public void onDestroy() {
179         if (mProgramLoadTask != null) {
180             mProgramLoadTask.cancel(true);
181             mProgramLoadTask = null;
182         }
183         getContext().getContentResolver().unregisterContentObserver(mContentObserver);
184         mHandler.removeCallbacksAndMessages(null);
185         mChannelDataManager.removeListener(mChannelListener);
186         mDvrDataManager.removeSeriesRecordingListener(mSeriesRecordingListener);
187         super.onDestroy();
188     }
189 
190     @Override
onCreateHeaderRowPresenter()191     public SchedulesHeaderRowPresenter onCreateHeaderRowPresenter() {
192         return new SchedulesHeaderRowPresenter.SeriesRecordingHeaderRowPresenter(getContext());
193     }
194 
195     @Override
onCreateRowPresenter()196     public ScheduleRowPresenter onCreateRowPresenter() {
197         return new SeriesScheduleRowPresenter(getContext());
198     }
199 
200     @Override
onCreateRowsAdapter(ClassPresenterSelector presenterSelector)201     public ScheduleRowAdapter onCreateRowsAdapter(ClassPresenterSelector presenterSelector) {
202         return new SeriesScheduleRowAdapter(getContext(), presenterSelector, mSeriesRecording);
203     }
204 
205     @Override
getFirstItemPosition()206     protected int getFirstItemPosition() {
207         if (mSeriesRecording != null
208                 && mSeriesRecording.getState() == SeriesRecording.STATE_SERIES_STOPPED) {
209             return 0;
210         }
211         return super.getFirstItemPosition();
212     }
213 
executeProgramLoadingTask()214     private void executeProgramLoadingTask() {
215         if (mProgramLoadTask != null) {
216             mProgramLoadTask.cancel(true);
217         }
218         mProgramLoadTask =
219                 new EpisodicProgramLoadTask(getContext(), mSeriesRecording) {
220                     @Override
221                     protected void onPostExecute(List<Program> programs) {
222                         mPrograms = programs == null ? Collections.EMPTY_LIST : programs;
223                         onProgramsUpdated();
224                     }
225                 };
226         mProgramLoadTask
227                 .setLoadCurrentProgram(true)
228                 .setLoadDisallowedProgram(true)
229                 .setLoadScheduledEpisode(true)
230                 .setIgnoreChannelOption(true)
231                 .execute();
232     }
233 }
234