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.analytics;
18 
19 import android.content.Context;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.support.annotation.MainThread;
23 
24 import com.android.tv.data.Channel;
25 import com.android.tv.data.ChannelDataManager;
26 import com.android.tv.util.RecurringRunner;
27 
28 import java.util.List;
29 import java.util.concurrent.TimeUnit;
30 
31 /**
32  * Periodically sends analytics data with the channel count.
33  *
34  * <p>
35  * <p>This should only be started from a user activity
36  * like {@link com.android.tv.MainActivity}.
37  */
38 @MainThread
39 public class SendChannelStatusRunnable implements Runnable {
40     private static final long SEND_CHANNEL_STATUS_INTERVAL_MS = TimeUnit.DAYS.toMillis(1);
41 
startChannelStatusRecurringRunner(Context context, Tracker tracker, ChannelDataManager channelDataManager)42     public static RecurringRunner startChannelStatusRecurringRunner(Context context,
43             Tracker tracker, ChannelDataManager channelDataManager) {
44 
45         final SendChannelStatusRunnable sendChannelStatusRunnable = new SendChannelStatusRunnable(
46                 channelDataManager, tracker);
47 
48         Runnable onStopRunnable = new Runnable() {
49             @Override
50             public void run() {
51                 sendChannelStatusRunnable.setDbLoadListener(null);
52             }
53         };
54         final RecurringRunner recurringRunner = new RecurringRunner(context,
55                 SEND_CHANNEL_STATUS_INTERVAL_MS, sendChannelStatusRunnable, onStopRunnable);
56 
57         if (channelDataManager.isDbLoadFinished()) {
58             sendChannelStatusRunnable.setDbLoadListener(null);
59             recurringRunner.start();
60         } else {
61             //Start the recurring runnable after the channel DB is finished loading.
62             sendChannelStatusRunnable.setDbLoadListener(new ChannelDataManager.Listener() {
63                 @Override
64                 public void onLoadFinished() {
65                     // This is called inside an iterator of Listeners so the remove step is done
66                     // via a post on the main thread
67                     new Handler(Looper.getMainLooper()).post(new Runnable() {
68                         @Override
69                         public void run() {
70                             sendChannelStatusRunnable.setDbLoadListener(null);
71                         }
72                     });
73                     recurringRunner.start();
74                 }
75 
76                 @Override
77                 public void onChannelListUpdated() { }
78 
79                 @Override
80                 public void onChannelBrowsableChanged() { }
81             });
82         }
83         return recurringRunner;
84     }
85 
86     private final ChannelDataManager mChannelDataManager;
87     private final Tracker mTracker;
88     private ChannelDataManager.Listener mListener;
89 
SendChannelStatusRunnable(ChannelDataManager channelDataManager, Tracker tracker)90     private SendChannelStatusRunnable(ChannelDataManager channelDataManager, Tracker tracker) {
91         mChannelDataManager = channelDataManager;
92         mTracker = tracker;
93     }
94 
95     @Override
run()96     public void run() {
97         int browsableChannelCount = 0;
98         List<Channel> channelList = mChannelDataManager.getChannelList();
99         for (Channel channel : channelList) {
100             if (channel.isBrowsable()) {
101                 ++browsableChannelCount;
102             }
103         }
104         mTracker.sendChannelCount(browsableChannelCount, channelList.size());
105     }
106 
setDbLoadListener(ChannelDataManager.Listener listener)107     private void setDbLoadListener(ChannelDataManager.Listener listener) {
108         if (mListener != null) {
109             mChannelDataManager.removeListener(mListener);
110         }
111         mListener = listener;
112         if (listener != null) {
113             mChannelDataManager.addListener(listener);
114         }
115     }
116 }
117