• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.dialer.list;
2 
3 import android.animation.LayoutTransition;
4 import android.app.ActionBar;
5 import android.app.Fragment;
6 import android.app.FragmentManager;
7 import android.content.Context;
8 import android.content.SharedPreferences;
9 import android.database.Cursor;
10 import android.os.Bundle;
11 import android.os.Trace;
12 import android.preference.PreferenceManager;
13 import android.provider.CallLog.Calls;
14 import android.support.v13.app.FragmentPagerAdapter;
15 import android.support.v4.view.ViewPager;
16 import android.support.v4.view.ViewPager.OnPageChangeListener;
17 import android.util.Log;
18 import android.view.LayoutInflater;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.widget.AbsListView;
22 import android.widget.ListView;
23 
24 import com.android.contacts.common.GeoUtil;
25 import com.android.contacts.common.list.ViewPagerTabs;
26 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
27 import com.android.dialer.DialtactsActivity;
28 import com.android.dialer.R;
29 import com.android.dialer.calllog.CallLogFragment;
30 import com.android.dialer.calllog.CallLogQueryHandler;
31 import com.android.dialer.calllog.ContactInfoHelper;
32 import com.android.dialer.util.DialerUtils;
33 import com.android.dialer.voicemail.VoicemailStatusHelper;
34 import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
35 import com.android.dialer.widget.ActionBarController;
36 import com.android.dialerbind.ObjectFactory;
37 
38 import java.util.ArrayList;
39 
40 /**
41  * Fragment that is used as the main screen of the Dialer.
42  *
43  * Contains a ViewPager that contains various contact lists like the Speed Dial list and the
44  * All Contacts list. This will also eventually contain the logic that allows sliding the
45  * ViewPager containing the lists up above the search bar and pin it against the top of the
46  * screen.
47  */
48 public class ListsFragment extends Fragment
49         implements ViewPager.OnPageChangeListener, CallLogQueryHandler.Listener {
50 
51     private static final boolean DEBUG = DialtactsActivity.DEBUG;
52     private static final String TAG = "ListsFragment";
53 
54     public static final int TAB_INDEX_SPEED_DIAL = 0;
55     public static final int TAB_INDEX_RECENTS = 1;
56     public static final int TAB_INDEX_ALL_CONTACTS = 2;
57     public static final int TAB_INDEX_VOICEMAIL = 3;
58 
59     public static final int TAB_COUNT_DEFAULT = 3;
60     public static final int TAB_COUNT_WITH_VOICEMAIL = 4;
61 
62     private static final int MAX_RECENTS_ENTRIES = 20;
63     // Oldest recents entry to display is 2 weeks old.
64     private static final long OLDEST_RECENTS_DATE = 1000L * 60 * 60 * 24 * 14;
65 
66     private static final String PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER =
67             "has_active_voicemail_provider";
68 
69     public interface HostInterface {
getActionBarController()70         public ActionBarController getActionBarController();
71     }
72 
73     private ActionBar mActionBar;
74     private ViewPager mViewPager;
75     private ViewPagerTabs mViewPagerTabs;
76     private ViewPagerAdapter mViewPagerAdapter;
77     private RemoveView mRemoveView;
78     private View mRemoveViewContent;
79 
80     private SpeedDialFragment mSpeedDialFragment;
81     private CallLogFragment mRecentsFragment;
82     private AllContactsFragment mAllContactsFragment;
83     private CallLogFragment mVoicemailFragment;
84 
85     private SharedPreferences mPrefs;
86     private boolean mHasActiveVoicemailProvider;
87     private boolean mHasFetchedVoicemailStatus;
88     private boolean mShowVoicemailTabAfterVoicemailStatusIsFetched;
89 
90     private VoicemailStatusHelper mVoicemailStatusHelper;
91     private ArrayList<OnPageChangeListener> mOnPageChangeListeners =
92             new ArrayList<OnPageChangeListener>();
93 
94     private String[] mTabTitles;
95     private int[] mTabIcons;
96 
97     /**
98      * The position of the currently selected tab.
99      */
100     private int mTabIndex = TAB_INDEX_SPEED_DIAL;
101 
102     public class ViewPagerAdapter extends FragmentPagerAdapter {
ViewPagerAdapter(FragmentManager fm)103         public ViewPagerAdapter(FragmentManager fm) {
104             super(fm);
105         }
106 
107         @Override
getItemId(int position)108         public long getItemId(int position) {
109             return getRtlPosition(position);
110         }
111 
112         @Override
getItem(int position)113         public Fragment getItem(int position) {
114             switch (getRtlPosition(position)) {
115                 case TAB_INDEX_SPEED_DIAL:
116                     mSpeedDialFragment = new SpeedDialFragment();
117                     return mSpeedDialFragment;
118                 case TAB_INDEX_RECENTS:
119                     mRecentsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL,
120                             MAX_RECENTS_ENTRIES, System.currentTimeMillis() - OLDEST_RECENTS_DATE);
121                     return mRecentsFragment;
122                 case TAB_INDEX_ALL_CONTACTS:
123                     mAllContactsFragment = new AllContactsFragment();
124                     return mAllContactsFragment;
125                 case TAB_INDEX_VOICEMAIL:
126                     mVoicemailFragment = new CallLogFragment(Calls.VOICEMAIL_TYPE);
127                     return mVoicemailFragment;
128             }
129             throw new IllegalStateException("No fragment at position " + position);
130         }
131 
132         @Override
instantiateItem(ViewGroup container, int position)133         public Object instantiateItem(ViewGroup container, int position) {
134             // On rotation the FragmentManager handles rotation. Therefore getItem() isn't called.
135             // Copy the fragments that the FragmentManager finds so that we can store them in
136             // instance variables for later.
137             final Fragment fragment =
138                     (Fragment) super.instantiateItem(container, position);
139             if (fragment instanceof SpeedDialFragment) {
140                 mSpeedDialFragment = (SpeedDialFragment) fragment;
141             } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_RECENTS) {
142                 mRecentsFragment = (CallLogFragment) fragment;
143             } else if (fragment instanceof AllContactsFragment) {
144                 mAllContactsFragment = (AllContactsFragment) fragment;
145             } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) {
146                 mVoicemailFragment = (CallLogFragment) fragment;
147             }
148             return fragment;
149         }
150 
151         @Override
getCount()152         public int getCount() {
153             return mHasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT;
154         }
155 
156         @Override
getPageTitle(int position)157         public CharSequence getPageTitle(int position) {
158             return mTabTitles[position];
159         }
160     }
161 
162     @Override
onCreate(Bundle savedInstanceState)163     public void onCreate(Bundle savedInstanceState) {
164         Trace.beginSection(TAG + " onCreate");
165         super.onCreate(savedInstanceState);
166 
167         Trace.beginSection(TAG + " getCurrentCountryIso");
168         final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
169         Trace.endSection();
170 
171         mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
172         mHasFetchedVoicemailStatus = false;
173 
174         mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
175         mHasActiveVoicemailProvider = mPrefs.getBoolean(
176                 PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, false);
177 
178         Trace.endSection();
179     }
180 
181     @Override
onResume()182     public void onResume() {
183         Trace.beginSection(TAG + " onResume");
184         super.onResume();
185         mActionBar = getActivity().getActionBar();
186         if (getUserVisibleHint()) {
187             sendScreenViewForCurrentPosition();
188         }
189 
190         // Fetch voicemail status to determine if we should show the voicemail tab.
191         CallLogQueryHandler callLogQueryHandler =
192                 new CallLogQueryHandler(getActivity(), getActivity().getContentResolver(), this);
193         callLogQueryHandler.fetchVoicemailStatus();
194         Trace.endSection();
195     }
196 
197     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)198     public View onCreateView(LayoutInflater inflater, ViewGroup container,
199             Bundle savedInstanceState) {
200         Trace.beginSection(TAG + " onCreateView");
201         Trace.beginSection(TAG + " inflate view");
202         final View parentView = inflater.inflate(R.layout.lists_fragment, container, false);
203         Trace.endSection();
204         Trace.beginSection(TAG + " setup views");
205         mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager);
206         mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
207         mViewPager.setAdapter(mViewPagerAdapter);
208         mViewPager.setOffscreenPageLimit(TAB_COUNT_WITH_VOICEMAIL - 1);
209         mViewPager.setOnPageChangeListener(this);
210         showTab(TAB_INDEX_SPEED_DIAL);
211 
212         mTabTitles = new String[TAB_COUNT_WITH_VOICEMAIL];
213         mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial);
214         mTabTitles[TAB_INDEX_RECENTS] = getResources().getString(R.string.tab_recents);
215         mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts);
216         mTabTitles[TAB_INDEX_VOICEMAIL] = getResources().getString(R.string.tab_voicemail);
217 
218         mTabIcons = new int[TAB_COUNT_WITH_VOICEMAIL];
219         mTabIcons[TAB_INDEX_SPEED_DIAL] = R.drawable.tab_speed_dial;
220         mTabIcons[TAB_INDEX_RECENTS] = R.drawable.tab_recents;
221         mTabIcons[TAB_INDEX_ALL_CONTACTS] = R.drawable.tab_contacts;
222         mTabIcons[TAB_INDEX_VOICEMAIL] = R.drawable.tab_voicemail;
223 
224         mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header);
225         mViewPagerTabs.setTabIcons(mTabIcons);
226         mViewPagerTabs.setViewPager(mViewPager);
227         addOnPageChangeListener(mViewPagerTabs);
228 
229         mRemoveView = (RemoveView) parentView.findViewById(R.id.remove_view);
230         mRemoveViewContent = parentView.findViewById(R.id.remove_view_content);
231 
232         Trace.endSection();
233         Trace.endSection();
234         return parentView;
235     }
236 
addOnPageChangeListener(OnPageChangeListener onPageChangeListener)237     public void addOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
238         if (!mOnPageChangeListeners.contains(onPageChangeListener)) {
239             mOnPageChangeListeners.add(onPageChangeListener);
240         }
241     }
242 
243     /**
244      * Shows the tab with the specified index. If the voicemail tab index is specified, but the
245      * voicemail status hasn't been fetched, it will try to show the tab after the voicemail status
246      * has been fetched.
247      */
showTab(int index)248     public void showTab(int index) {
249         if (index == TAB_INDEX_VOICEMAIL) {
250             if (mHasActiveVoicemailProvider) {
251                 mViewPager.setCurrentItem(getRtlPosition(TAB_INDEX_VOICEMAIL));
252             } else if (!mHasFetchedVoicemailStatus) {
253                 // Try to show the voicemail tab after the voicemail status returns.
254                 mShowVoicemailTabAfterVoicemailStatusIsFetched = true;
255             }
256         } else {
257             mViewPager.setCurrentItem(getRtlPosition(index));
258         }
259     }
260 
261     @Override
onPageScrolled(int position, float positionOffset, int positionOffsetPixels)262     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
263         mTabIndex = getRtlPosition(position);
264 
265         final int count = mOnPageChangeListeners.size();
266         for (int i = 0; i < count; i++) {
267             mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset,
268                     positionOffsetPixels);
269         }
270     }
271 
272     @Override
onPageSelected(int position)273     public void onPageSelected(int position) {
274         mTabIndex = getRtlPosition(position);
275 
276         // Show the tab which has been selected instead.
277         mShowVoicemailTabAfterVoicemailStatusIsFetched = false;
278 
279         final int count = mOnPageChangeListeners.size();
280         for (int i = 0; i < count; i++) {
281             mOnPageChangeListeners.get(i).onPageSelected(position);
282         }
283         sendScreenViewForCurrentPosition();
284     }
285 
286     @Override
onPageScrollStateChanged(int state)287     public void onPageScrollStateChanged(int state) {
288         final int count = mOnPageChangeListeners.size();
289         for (int i = 0; i < count; i++) {
290             mOnPageChangeListeners.get(i).onPageScrollStateChanged(state);
291         }
292     }
293 
294     @Override
onVoicemailStatusFetched(Cursor statusCursor)295     public void onVoicemailStatusFetched(Cursor statusCursor) {
296         mHasFetchedVoicemailStatus = true;
297 
298         if (getActivity() == null || getActivity().isFinishing()) {
299             return;
300         }
301 
302         // Update mHasActiveVoicemailProvider, which controls the number of tabs displayed.
303         boolean hasActiveVoicemailProvider =
304                 mVoicemailStatusHelper.getNumberActivityVoicemailSources(statusCursor) > 0;
305         if (hasActiveVoicemailProvider != mHasActiveVoicemailProvider) {
306             mHasActiveVoicemailProvider = hasActiveVoicemailProvider;
307             mViewPagerAdapter.notifyDataSetChanged();
308             mViewPagerTabs.setViewPager(mViewPager);
309 
310             mPrefs.edit()
311                     .putBoolean(PREF_KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, hasActiveVoicemailProvider)
312                     .commit();
313         }
314 
315         if (mHasActiveVoicemailProvider && mShowVoicemailTabAfterVoicemailStatusIsFetched) {
316             mShowVoicemailTabAfterVoicemailStatusIsFetched = false;
317             showTab(TAB_INDEX_VOICEMAIL);
318         }
319     }
320 
321     @Override
onCallsFetched(Cursor statusCursor)322     public boolean onCallsFetched(Cursor statusCursor) {
323         // Return false; did not take ownership of cursor
324         return false;
325     }
326 
getCurrentTabIndex()327     public int getCurrentTabIndex() {
328         return mTabIndex;
329     }
330 
showRemoveView(boolean show)331     public void showRemoveView(boolean show) {
332         mRemoveViewContent.setVisibility(show ? View.VISIBLE : View.GONE);
333         mRemoveView.setAlpha(show ? 0 : 1);
334         mRemoveView.animate().alpha(show ? 1 : 0).start();
335     }
336 
shouldShowActionBar()337     public boolean shouldShowActionBar() {
338         // TODO: Update this based on scroll state.
339         return mActionBar != null;
340     }
341 
getSpeedDialFragment()342     public SpeedDialFragment getSpeedDialFragment() {
343         return mSpeedDialFragment;
344     }
345 
getRemoveView()346     public RemoveView getRemoveView() {
347         return mRemoveView;
348     }
349 
getTabCount()350     public int getTabCount() {
351         return mViewPagerAdapter.getCount();
352     }
353 
getRtlPosition(int position)354     private int getRtlPosition(int position) {
355         if (DialerUtils.isRtl()) {
356             return mViewPagerAdapter.getCount() - 1 - position;
357         }
358         return position;
359     }
360 
sendScreenViewForCurrentPosition()361     public void sendScreenViewForCurrentPosition() {
362         if (!isResumed()) {
363             return;
364         }
365 
366         String fragmentName;
367         switch (getCurrentTabIndex()) {
368             case TAB_INDEX_SPEED_DIAL:
369                 fragmentName = SpeedDialFragment.class.getSimpleName();
370                 break;
371             case TAB_INDEX_RECENTS:
372                 fragmentName = CallLogFragment.class.getSimpleName() + "#Recents";
373                 break;
374             case TAB_INDEX_ALL_CONTACTS:
375                 fragmentName = AllContactsFragment.class.getSimpleName();
376                 break;
377             case TAB_INDEX_VOICEMAIL:
378                 fragmentName = CallLogFragment.class.getSimpleName() + "#Voicemail";
379             default:
380                 return;
381         }
382         AnalyticsUtil.sendScreenView(fragmentName, getActivity(), null);
383     }
384 }
385