• 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.testing;
18 
19 import android.support.annotation.NonNull;
20 import android.support.annotation.Nullable;
21 import android.util.Range;
22 import com.android.tv.data.ChannelImpl;
23 import com.android.tv.data.ChannelNumber;
24 import com.android.tv.data.Lineup;
25 import com.android.tv.data.Program;
26 import com.android.tv.data.api.Channel;
27 import com.android.tv.data.epg.EpgReader;
28 import com.android.tv.dvr.data.SeriesInfo;
29 import com.google.common.base.Function;
30 import com.google.common.base.Predicate;
31 import com.google.common.collect.ImmutableList;
32 import com.google.common.collect.ImmutableMap;
33 import com.google.common.collect.Iterables;
34 import com.google.common.collect.LinkedListMultimap;
35 import com.google.common.collect.ListMultimap;
36 import java.util.Collection;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41 
42 /** Fake {@link EpgReader} for testing. */
43 public final class FakeEpgReader implements EpgReader {
44     public final ListMultimap<String, Lineup> zip2lineups = LinkedListMultimap.create(2);
45     public final ListMultimap<String, Channel> lineup2Channels = LinkedListMultimap.create(2);
46     public final ListMultimap<String, Program> epgChannelId2Programs = LinkedListMultimap.create(2);
47     public final FakeClock fakeClock;
48 
FakeEpgReader(FakeClock fakeClock)49     public FakeEpgReader(FakeClock fakeClock) {
50         this.fakeClock = fakeClock;
51     }
52 
53     @Override
isAvailable()54     public boolean isAvailable() {
55         return true;
56     }
57 
58     @Override
getEpgTimestamp()59     public long getEpgTimestamp() {
60         return fakeClock.currentTimeMillis();
61     }
62 
63     @Override
setRegionCode(String regionCode)64     public void setRegionCode(String regionCode) {}
65 
66     @Override
getLineups(@onNull String postalCode)67     public List<Lineup> getLineups(@NonNull String postalCode) {
68         return zip2lineups.get(postalCode);
69     }
70 
71     @Override
getChannelNumbers(@onNull String lineupId)72     public List<String> getChannelNumbers(@NonNull String lineupId) {
73         return null;
74     }
75 
76     @Override
getChannels(Set<Channel> inputChannels, @NonNull String lineupId)77     public Set<EpgChannel> getChannels(Set<Channel> inputChannels, @NonNull String lineupId) {
78         Set<EpgChannel> result = new HashSet<>();
79         List<Channel> lineupChannels = lineup2Channels.get(lineupId);
80         for (Channel channel : lineupChannels) {
81             Channel match =
82                     Iterables.find(
83                             inputChannels,
84                             new Predicate<Channel>() {
85                                 @Override
86                                 public boolean apply(@Nullable Channel inputChannel) {
87                                     return ChannelNumber.equivalent(
88                                             inputChannel.getDisplayNumber(),
89                                             channel.getDisplayNumber());
90                                 }
91                             },
92                             null);
93             if (match != null) {
94                 ChannelImpl updatedChannel = new ChannelImpl.Builder(match).build();
95                 updatedChannel.setLogoUri(channel.getLogoUri());
96                 result.add(EpgChannel.createEpgChannel(updatedChannel, channel.getDisplayNumber()));
97             }
98         }
99         return result;
100     }
101 
102     @Override
preloadChannels(@onNull String lineupId)103     public void preloadChannels(@NonNull String lineupId) {}
104 
105     @Override
clearCachedChannels(@onNull String lineupId)106     public void clearCachedChannels(@NonNull String lineupId) {}
107 
108     @Override
getPrograms(EpgChannel epgChannel)109     public List<Program> getPrograms(EpgChannel epgChannel) {
110         return ImmutableList.copyOf(
111                 Iterables.transform(
112                         epgChannelId2Programs.get(epgChannel.getEpgChannelId()),
113                         updateWith(epgChannel)));
114     }
115 
116     @Override
getPrograms( @onNull Set<EpgChannel> epgChannels, long duration)117     public Map<EpgChannel, Collection<Program>> getPrograms(
118             @NonNull Set<EpgChannel> epgChannels, long duration) {
119         Range<Long> validRange =
120                 Range.create(
121                         fakeClock.currentTimeMillis(), fakeClock.currentTimeMillis() + duration);
122         ImmutableMap.Builder<EpgChannel, Collection<Program>> mapBuilder = ImmutableMap.builder();
123         for (EpgChannel epgChannel : epgChannels) {
124             Iterable<Program> programs = getPrograms(epgChannel);
125 
126             mapBuilder.put(
127                     epgChannel,
128                     ImmutableList.copyOf(Iterables.filter(programs, isProgramDuring(validRange))));
129         }
130         return mapBuilder.build();
131     }
132 
updateWith(final EpgChannel channel)133     protected Function<Program, Program> updateWith(final EpgChannel channel) {
134         return new Function<Program, Program>() {
135             @Nullable
136             @Override
137             public Program apply(@Nullable Program program) {
138                 return new Program.Builder(program)
139                         .setChannelId(channel.getChannel().getId())
140                         .setPackageName(channel.getChannel().getPackageName())
141                         .build();
142             }
143         };
144     }
145 
146     /**
147      * True if the start time or the end time is {@link Range#contains contained (inclusive)} in the
148      * range
149      */
150     protected Predicate<Program> isProgramDuring(final Range<Long> validRange) {
151         return new Predicate<Program>() {
152             @Override
153             public boolean apply(@Nullable Program program) {
154                 return validRange.contains(program.getStartTimeUtcMillis())
155                         || validRange.contains(program.getEndTimeUtcMillis());
156             }
157         };
158     }
159 
160     @Override
161     public SeriesInfo getSeriesInfo(@NonNull String seriesId) {
162         return null;
163     }
164 }
165