Home | History | Annotate | Download | only in menu
      1 /*
      2  * Copyright (C) 2015 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.menu;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.media.tv.TvInputInfo;
     22 import android.os.Build;
     23 import android.support.v4.os.BuildCompat;
     24 import android.view.View;
     25 
     26 import com.android.tv.MainActivity;
     27 import com.android.tv.R;
     28 import com.android.tv.TvApplication;
     29 import com.android.tv.analytics.Tracker;
     30 import com.android.tv.common.feature.CommonFeatures;
     31 import com.android.tv.data.Channel;
     32 import com.android.tv.recommendation.Recommender;
     33 import com.android.tv.util.SetupUtils;
     34 import com.android.tv.util.TvInputManagerHelper;
     35 import com.android.tv.util.Utils;
     36 
     37 import java.util.ArrayList;
     38 import java.util.List;
     39 
     40 /**
     41  * An adapter of the Channels row.
     42  */
     43 public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> {
     44     // There are four special cards: guide, setup, dvr, record, applink.
     45     private static final int SIZE_OF_VIEW_TYPE = 5;
     46 
     47     private final Context mContext;
     48     private final Tracker mTracker;
     49     private final Recommender mRecommender;
     50     private final int mMaxCount;
     51     private final int mMinCount;
     52     private final boolean mDvrFeatureEnabled;
     53     private final int[] mViewType = new int[SIZE_OF_VIEW_TYPE];
     54 
     55     private final View.OnClickListener mGuideOnClickListener = new View.OnClickListener() {
     56         @Override
     57         public void onClick(View view) {
     58             mTracker.sendMenuClicked(R.string.channels_item_program_guide);
     59             getMainActivity().getOverlayManager().showProgramGuide();
     60         }
     61     };
     62 
     63     private final View.OnClickListener mSetupOnClickListener = new View.OnClickListener() {
     64         @Override
     65         public void onClick(View view) {
     66             mTracker.sendMenuClicked(R.string.channels_item_setup);
     67             getMainActivity().getOverlayManager().showSetupFragment();
     68         }
     69     };
     70 
     71     private final View.OnClickListener mDvrOnClickListener = new View.OnClickListener() {
     72         @Override
     73         public void onClick(View view) {
     74             Utils.showToastMessageForDeveloperFeature(view.getContext());
     75             mTracker.sendMenuClicked(R.string.channels_item_dvr);
     76             getMainActivity().getOverlayManager().showDvrManager();
     77         }
     78     };
     79 
     80     private final View.OnClickListener mRecordOnClickListener = new View.OnClickListener() {
     81         @Override
     82         public void onClick(View view) {
     83             Utils.showToastMessageForDeveloperFeature(view.getContext());
     84             RecordCardView v = ((RecordCardView) view);
     85             boolean isRecording = v.isRecording();
     86             mTracker.sendMenuClicked(isRecording ? R.string.channels_item_record_start
     87                     : R.string.channels_item_record_stop);
     88             if (!isRecording) {
     89                 v.startRecording();
     90             } else {
     91                 v.stopRecording();
     92             }
     93         }
     94     };
     95 
     96     private final View.OnClickListener mAppLinkOnClickListener = new View.OnClickListener() {
     97         @Override
     98         public void onClick(View view) {
     99             mTracker.sendMenuClicked(R.string.channels_item_app_link);
    100             Intent intent = ((AppLinkCardView) view).getIntent();
    101             if (intent != null) {
    102                 getMainActivity().startActivitySafe(intent);
    103             }
    104         }
    105     };
    106 
    107     private final View.OnClickListener mChannelOnClickListener = new View.OnClickListener() {
    108         @Override
    109         public void onClick(View view) {
    110             // Always send the label "Channels" because the channel ID or name or number might be
    111             // sensitive.
    112             mTracker.sendMenuClicked(R.string.menu_title_channels);
    113             getMainActivity().tuneToChannel((Channel) view.getTag());
    114             getMainActivity().hideOverlaysForTune();
    115         }
    116     };
    117 
    118     public ChannelsRowAdapter(Context context, Recommender recommender,
    119             int minCount, int maxCount) {
    120         super(context);
    121         mTracker = TvApplication.getSingletons(context).getTracker();
    122         mContext = context;
    123         mRecommender = recommender;
    124         mMinCount = minCount;
    125         mMaxCount = maxCount;
    126         mDvrFeatureEnabled = CommonFeatures.DVR.isEnabled(mContext) && BuildCompat.isAtLeastN();
    127     }
    128 
    129     @Override
    130     public int getItemViewType(int position) {
    131         if (position >= SIZE_OF_VIEW_TYPE) {
    132             return R.layout.menu_card_channel;
    133         }
    134         return mViewType[position];
    135     }
    136 
    137     @Override
    138     protected int getLayoutResId(int viewType) {
    139         return viewType;
    140     }
    141 
    142     @Override
    143     public void onBindViewHolder(MyViewHolder viewHolder, int position) {
    144         super.onBindViewHolder(viewHolder, position);
    145 
    146         int viewType = getItemViewType(position);
    147         if (viewType == R.layout.menu_card_guide) {
    148             viewHolder.itemView.setOnClickListener(mGuideOnClickListener);
    149         } else if (viewType == R.layout.menu_card_setup) {
    150             viewHolder.itemView.setOnClickListener(mSetupOnClickListener);
    151         } else if (viewType == R.layout.menu_card_app_link) {
    152             viewHolder.itemView.setOnClickListener(mAppLinkOnClickListener);
    153         } else if (viewType == R.layout.menu_card_dvr) {
    154             viewHolder.itemView.setOnClickListener(mDvrOnClickListener);
    155         } else if (viewType == R.layout.menu_card_record) {
    156             viewHolder.itemView.setOnClickListener(mRecordOnClickListener);
    157         } else {
    158             viewHolder.itemView.setTag(getItemList().get(position));
    159             viewHolder.itemView.setOnClickListener(mChannelOnClickListener);
    160         }
    161     }
    162 
    163     @Override
    164     public void update() {
    165         List<Channel> channelList = new ArrayList<>();
    166         Channel dummyChannel = new Channel.Builder().build();
    167         // For guide item
    168         channelList.add(dummyChannel);
    169         // For setup item
    170         TvInputManagerHelper inputManager = TvApplication.getSingletons(mContext)
    171                 .getTvInputManagerHelper();
    172         boolean showSetupCard = SetupUtils.getInstance(mContext).hasNewInput(inputManager);
    173         Channel currentChannel = ((MainActivity) mContext).getCurrentChannel();
    174         boolean showAppLinkCard = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    175                 && currentChannel != null
    176                 && currentChannel.getAppLinkType(mContext) != Channel.APP_LINK_TYPE_NONE;
    177         boolean showDvrCard = false;
    178         boolean showRecordCard = false;
    179         if (mDvrFeatureEnabled) {
    180             for (TvInputInfo info : inputManager.getTvInputInfos(true, true)) {
    181                 if (info.canRecord()) {
    182                     showDvrCard = true;
    183                     break;
    184                 }
    185             }
    186             if (currentChannel != null && currentChannel.getInputId() != null) {
    187                 TvInputInfo inputInfo = inputManager.getTvInputInfo(currentChannel.getInputId());
    188                 if ((inputInfo.canRecord() && inputInfo.getTunerCount() > 1)) {
    189                     showRecordCard = true;
    190                 }
    191             }
    192         }
    193 
    194         mViewType[0] = R.layout.menu_card_guide;
    195         int index = 1;
    196         if (showSetupCard) {
    197             channelList.add(dummyChannel);
    198             mViewType[index++] = R.layout.menu_card_setup;
    199         }
    200         if (showDvrCard) {
    201             channelList.add(dummyChannel);
    202             mViewType[index++] = R.layout.menu_card_dvr;
    203         }
    204         if (showRecordCard) {
    205             channelList.add(currentChannel);
    206             mViewType[index++] = R.layout.menu_card_record;
    207         }
    208         if (showAppLinkCard) {
    209             channelList.add(currentChannel);
    210             mViewType[index++] = R.layout.menu_card_app_link;
    211         }
    212         for ( ; index < mViewType.length; ++index) {
    213             mViewType[index] = R.layout.menu_card_channel;
    214         }
    215         channelList.addAll(getRecentChannels());
    216         setItemList(channelList);
    217     }
    218 
    219     private List<Channel> getRecentChannels() {
    220         List<Channel> channelList = new ArrayList<>();
    221         for (Channel channel : mRecommender.recommendChannels(mMaxCount)) {
    222             if (channel.isBrowsable()) {
    223                 channelList.add(channel);
    224             }
    225         }
    226         int count = channelList.size();
    227         // If the number of recommended channels is not enough, add more from the recent channel
    228         // list.
    229         if (count < mMinCount && mContext instanceof MainActivity) {
    230             for (long channelId : ((MainActivity) mContext).getRecentChannels()) {
    231                 Channel channel = mRecommender.getChannel(channelId);
    232                 if (channel == null || channelList.contains(channel)
    233                         || !channel.isBrowsable()) {
    234                    continue;
    235                 }
    236                 channelList.add(channel);
    237                 if (++count >= mMinCount) {
    238                     break;
    239                 }
    240             }
    241         }
    242         return channelList;
    243     }
    244 }
    245