13d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer/* 23d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Copyright (C) 2015 The Android Open Source Project 33d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * 43d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License"); 53d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * you may not use this file except in compliance with the License. 63d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * You may obtain a copy of the License at 73d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * 83d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * http://www.apache.org/licenses/LICENSE-2.0 93d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * 103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Unless required by applicable law or agreed to in writing, software 113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS, 123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * See the License for the specific language governing permissions and 143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * limitations under the License. 153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */ 163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerpackage com.android.car.dialer; 173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.ContentResolver; 193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.Context; 203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.CursorLoader; 2197b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chenimport android.content.res.Resources; 223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.database.ContentObserver; 233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.database.Cursor; 243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.graphics.Canvas; 2597b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chenimport android.graphics.Paint; 263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.net.Uri; 273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.os.Bundle; 283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.os.Handler; 293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.support.annotation.Nullable; 303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.support.v4.app.Fragment; 313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.support.v7.widget.RecyclerView; 323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.util.Log; 333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.LayoutInflater; 343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.View; 353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.ViewGroup; 363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.widget.LinearLayout; 3717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen 383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport com.android.car.dialer.telecom.PhoneLoader; 393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport com.android.car.dialer.telecom.UiCallManager; 409c60bc83bd37ae212e66f2e27b821cebbe7beeb2Rakesh Iyerimport com.android.car.view.PagedListView; 413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer/** 433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Contains a list of contacts. The call types can be any of the CALL_TYPE_* fields from 443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * {@link PhoneLoader}. 453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */ 463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerpublic class StrequentsFragment extends Fragment { 473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private static final String TAG = "Em.StrequentsFrag"; 483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 4917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen private static final String KEY_MAX_CLICKS = "max_clicks"; 5017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen private static final int DEFAULT_MAX_CLICKS = 6; 513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 526ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan private UiCallManager mUiCallManager; 533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private StrequentsAdapter mAdapter; 543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private CursorLoader mSpeedialCursorLoader; 553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private CursorLoader mCallLogCursorLoader; 563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private Context mContext; 573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private PagedListView mListView; 583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private Cursor mStrequentCursor; 593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private Cursor mCallLogCursor; 603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private boolean mHasLoadedData; 613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 626ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan public static StrequentsFragment newInstance(UiCallManager callManager) { 636ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan StrequentsFragment fragment = new StrequentsFragment(); 646ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan fragment.mUiCallManager = callManager; 656ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan return fragment; 666ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan } 676ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan 683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onCreate(@Nullable Bundle savedInstanceState) { 703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer super.onCreate(savedInstanceState); 713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "onCreate"); 733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public View onCreateView(LayoutInflater inflater, ViewGroup container, 783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Bundle savedInstanceState) { 793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "onCreateView"); 813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 836f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan mContext = getContext(); 843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer View view = inflater.inflate(R.layout.strequents_fragment, container, false); 863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView = (PagedListView) view.findViewById(R.id.list_view); 873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView.getLayoutManager().setOffsetRows(true); 883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mSpeedialCursorLoader = PhoneLoader.registerCallObserver(PhoneLoader.CALL_TYPE_SPEED_DIAL, 906f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan mContext, (loader, cursor) -> { 916f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan if (Log.isLoggable(TAG, Log.DEBUG)) { 926f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan Log.d(TAG, "PhoneLoader: onLoadComplete (CALL_TYPE_SPEED_DIAL)"); 936f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan } 943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 956f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan onLoadStrequentCursor(cursor); 963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 976f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan if (mContext != null) { 9897b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen mListView.addItemDecoration(new Decoration(mContext)); 996f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan } 1006f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan }); 1013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // Get the latest call log from the call logs history. 1033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mCallLogCursorLoader = PhoneLoader.registerCallObserver(PhoneLoader.CALL_TYPE_ALL, mContext, 1046f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan (loader, cursor) -> { 1056f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan if (Log.isLoggable(TAG, Log.DEBUG)) { 1066f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan Log.d(TAG, "PhoneLoader: onLoadComplete (CALL_TYPE_ALL)"); 1076f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan } 1086f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan onLoadCallLogCursor(cursor); 1096f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan }); 1103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer ContentResolver contentResolver = mContext.getContentResolver(); 1123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer contentResolver.registerContentObserver(mSpeedialCursorLoader.getUri(), 1133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer false, new SpeedDialContentObserver(new Handler())); 1143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer contentResolver.registerContentObserver(mCallLogCursorLoader.getUri(), 1153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer false, new CallLogContentObserver(new Handler())); 1163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // Maximum number of forward acting clicks the user can perform 11817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen Bundle args = getArguments(); 11917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen int maxClicks = args == null 12017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen ? DEFAULT_MAX_CLICKS 12117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen : args.getInt(KEY_MAX_CLICKS, DEFAULT_MAX_CLICKS /* G.maxForwardClicks.get() */); 1223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // We want to show one fewer page than max clicks to allow clicking on an item, 1233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // but, the first page is "free" since it doesn't take any clicks to show 1243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer final int maxPages = maxClicks < 0 ? -1 : maxClicks; 1253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.VERBOSE)) { 1263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.v(TAG, "Max clicks: " + maxClicks + ", Max pages: " + maxPages); 1273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView.setLightMode(); 1306ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan mAdapter = new StrequentsAdapter(mContext, mUiCallManager); 1313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setStrequentsListener(viewHolder -> { 1323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 1333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "onContactedClicked"); 1343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1366ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan mUiCallManager.safePlaceCall((String) viewHolder.itemView.getTag(), false); 1373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer }); 1383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView.setMaxPages(maxPages); 1393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView.setAdapter(mAdapter); 1403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 1423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "setItemAnimator"); 1433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mListView.getRecyclerView().setItemAnimator(new StrequentsItemAnimator()); 1463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer return view; 1473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 1503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onDestroyView() { 1513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer super.onDestroyView(); 1523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 1543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "onDestroyView"); 1553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setStrequentCursor(null); 1583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setLastCallCursor(null); 1593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mCallLogCursorLoader.reset(); 1603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mSpeedialCursorLoader.reset(); 1613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mCallLogCursor = null; 1623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mStrequentCursor = null; 1633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mHasLoadedData = false; 1643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mContext = null; 1653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private void loadDataIntoAdapter() { 1683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 1693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "loadDataIntoAdapter"); 1703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mHasLoadedData = true; 1733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setLastCallCursor(mCallLogCursor); 1743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setStrequentCursor(mStrequentCursor); 1753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private void onLoadStrequentCursor(Cursor cursor) { 1783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 1793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "onLoadStrequentCursor"); 1803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (cursor == null) { 1833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer throw new IllegalArgumentException( 1843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer "cursor was null in on speed dial fetched"); 1853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mStrequentCursor = cursor; 1883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (mCallLogCursor != null) { 1893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (mHasLoadedData) { 1903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setStrequentCursor(cursor); 1913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } else { 1923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer loadDataIntoAdapter(); 1933d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 1963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 1973d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private void onLoadCallLogCursor(Cursor cursor) { 1983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (cursor == null) { 1993d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer throw new IllegalArgumentException( 2003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer "cursor was null in on calls fetched"); 2013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mCallLogCursor = cursor; 2043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (mStrequentCursor != null) { 2053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (mHasLoadedData) { 2063d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mAdapter.setLastCallCursor(cursor); 2073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } else { 2083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer loadDataIntoAdapter(); 2093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer /** 2143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * A {@link ContentResolver} that is responsible for reloading the user's starred and frequent 2153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * contacts. 2163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */ 2173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private class SpeedDialContentObserver extends ContentObserver { 2183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public SpeedDialContentObserver(Handler handler) { 2193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer super(handler); 2203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 2233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onChange(boolean selfChange) { 2243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer onChange(selfChange, null); 2253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 2283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onChange(boolean selfChange, Uri uri) { 2293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 2303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "SpeedDialContentObserver onChange() called. Reloading strequents."); 2313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mSpeedialCursorLoader.startLoading(); 2333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer /** 2373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * A {@link ContentResolver} that is responsible for reloading the user's recent calls. 2383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */ 2393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private class CallLogContentObserver extends ContentObserver { 2403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public CallLogContentObserver(Handler handler) { 2413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer super(handler); 2423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 2453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onChange(boolean selfChange) { 2463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer onChange(selfChange, null); 2473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 2503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onChange(boolean selfChange, Uri uri) { 2513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (Log.isLoggable(TAG, Log.DEBUG)) { 2523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer Log.d(TAG, "CallLogContentObserver onChange() called. Reloading call log."); 2533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mCallLogCursorLoader.startLoading(); 2553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer /** 25997b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen * Decoration for the speed dial cards. This ItemDecoration will not show a divider between 26097b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen * the dialpad item and the first speed dial item and the divider is offset but a couple of 26197b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen * pixels to offset the fact that the cards overlap. 2623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */ 26397b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen private static class Decoration extends RecyclerView.ItemDecoration { 26497b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen private final Paint mPaint; 2653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer private final int mPaintAlpha; 26697b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen private final int mDividerHeight; 2673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public Decoration(Context context) { 26997b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen Resources res = context.getResources(); 27097b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen mPaint = new Paint(); 27197b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen mPaint.setColor(res.getColor(R.color.car_list_divider)); 27297b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen mDividerHeight = res.getDimensionPixelSize(R.dimen.car_divider_height); 2733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mPaintAlpha = mPaint.getAlpha(); 2743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer @Override 2773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 2783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer StrequentsAdapter adapter = (StrequentsAdapter) parent.getAdapter(); 2793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (adapter.getItemCount() <= 0) { 2813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer return; 2823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer final int childCount = parent.getChildCount(); 2853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // Don't draw decoration line on last item of the list. 2873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer for (int i = 0; i < childCount - 1; i++) { 2883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer final View child = parent.getChildAt(i); 2893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // If the child is focused then the decoration will look bad with the focus 2913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // highlight so don't draw it. 2923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (child.isFocused()) { 2933d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer continue; 2943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 2953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 2963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer // The left edge of the divider should align with the left edge of text_container. 29797b319e44253a215dab1e6d626fcdc5f56d3867cAnthony Chen LinearLayout container = child.findViewById(R.id.container); 2983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer View textContainer = child.findViewById(R.id.text_container); 2993d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer View card = child.findViewById(R.id.call_log_card); 3003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 3013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer int left = textContainer.getLeft() + container.getLeft() + card.getLeft(); 3023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer int right = left + textContainer.getWidth(); 3033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 3043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); 3053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer int bottom = child.getBottom() + lp.bottomMargin 30617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen + Math.round(child.getTranslationY()); 3073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer int top = bottom - mDividerHeight; 3083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 3093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer if (top >= c.getHeight() || top < 0) { 3103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer break; 3113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 3123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer 3133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer mPaint.setAlpha(Math.round(container.getAlpha() * mPaintAlpha)); 3143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer c.drawRect(left, top, right, bottom, mPaint); 3153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 3163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 3173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer } 3183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer} 319