1 /* 2 * Copyright (C) 2013 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 package com.android.dialer.app.calllog; 17 18 import android.app.Fragment; 19 import android.app.FragmentManager; 20 import android.content.Intent; 21 import android.os.Bundle; 22 import android.provider.CallLog; 23 import android.provider.CallLog.Calls; 24 import android.support.annotation.VisibleForTesting; 25 import android.support.design.widget.Snackbar; 26 import android.support.v13.app.FragmentPagerAdapter; 27 import android.support.v4.view.ViewPager; 28 import android.support.v7.app.ActionBar; 29 import android.view.Menu; 30 import android.view.MenuInflater; 31 import android.view.MenuItem; 32 import android.view.ViewGroup; 33 import com.android.contacts.common.list.ViewPagerTabs; 34 import com.android.dialer.app.R; 35 import com.android.dialer.calldetails.OldCallDetailsActivity; 36 import com.android.dialer.common.Assert; 37 import com.android.dialer.constants.ActivityRequestCodes; 38 import com.android.dialer.database.CallLogQueryHandler; 39 import com.android.dialer.logging.Logger; 40 import com.android.dialer.logging.ScreenEvent; 41 import com.android.dialer.logging.UiAction; 42 import com.android.dialer.performancereport.PerformanceReport; 43 import com.android.dialer.postcall.PostCall; 44 import com.android.dialer.util.TransactionSafeActivity; 45 import com.android.dialer.util.ViewUtil; 46 47 /** Activity for viewing call history. */ 48 public class CallLogActivity extends TransactionSafeActivity 49 implements ViewPager.OnPageChangeListener { 50 51 @VisibleForTesting static final int TAB_INDEX_ALL = 0; 52 @VisibleForTesting static final int TAB_INDEX_MISSED = 1; 53 private static final int TAB_INDEX_COUNT = 2; 54 private ViewPager viewPager; 55 private ViewPagerTabs viewPagerTabs; 56 private ViewPagerAdapter viewPagerAdapter; 57 private CallLogFragment allCallsFragment; 58 private CallLogFragment missedCallsFragment; 59 private String[] tabTitles; 60 private boolean isResumed; 61 private int selectedPageIndex; 62 63 @Override onCreate(Bundle savedInstanceState)64 protected void onCreate(Bundle savedInstanceState) { 65 super.onCreate(savedInstanceState); 66 67 setContentView(R.layout.call_log_activity); 68 getWindow().setBackgroundDrawable(null); 69 70 final ActionBar actionBar = getSupportActionBar(); 71 actionBar.setDisplayShowHomeEnabled(true); 72 actionBar.setDisplayHomeAsUpEnabled(true); 73 actionBar.setDisplayShowTitleEnabled(true); 74 actionBar.setElevation(0); 75 76 int startingTab = TAB_INDEX_ALL; 77 final Intent intent = getIntent(); 78 if (intent != null) { 79 final int callType = intent.getIntExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, -1); 80 if (callType == CallLog.Calls.MISSED_TYPE) { 81 startingTab = TAB_INDEX_MISSED; 82 } 83 } 84 selectedPageIndex = startingTab; 85 86 tabTitles = new String[TAB_INDEX_COUNT]; 87 tabTitles[0] = getString(R.string.call_log_all_title); 88 tabTitles[1] = getString(R.string.call_log_missed_title); 89 90 viewPager = (ViewPager) findViewById(R.id.call_log_pager); 91 92 viewPagerAdapter = new ViewPagerAdapter(getFragmentManager()); 93 viewPager.setAdapter(viewPagerAdapter); 94 viewPager.setOffscreenPageLimit(1); 95 viewPager.setOnPageChangeListener(this); 96 97 viewPagerTabs = (ViewPagerTabs) findViewById(R.id.viewpager_header); 98 99 viewPagerTabs.setViewPager(viewPager); 100 viewPager.setCurrentItem(startingTab); 101 } 102 103 @Override onResume()104 protected void onResume() { 105 // Some calls may not be recorded (eg. from quick contact), 106 // so we should restart recording after these calls. (Recorded call is stopped) 107 PostCall.restartPerformanceRecordingIfARecentCallExist(this); 108 if (!PerformanceReport.isRecording()) { 109 PerformanceReport.startRecording(); 110 } 111 112 isResumed = true; 113 super.onResume(); 114 sendScreenViewForChildFragment(); 115 } 116 117 @Override onPause()118 protected void onPause() { 119 isResumed = false; 120 super.onPause(); 121 } 122 123 @Override onStop()124 protected void onStop() { 125 if (!isChangingConfigurations() && viewPager != null) { 126 // Make sure current index != selectedPageIndex 127 selectedPageIndex = -1; 128 updateMissedCalls(viewPager.getCurrentItem()); 129 } 130 super.onStop(); 131 } 132 133 @Override onCreateOptionsMenu(Menu menu)134 public boolean onCreateOptionsMenu(Menu menu) { 135 final MenuInflater inflater = getMenuInflater(); 136 inflater.inflate(R.menu.call_log_options, menu); 137 return true; 138 } 139 140 @Override onPrepareOptionsMenu(Menu menu)141 public boolean onPrepareOptionsMenu(Menu menu) { 142 final MenuItem itemDeleteAll = menu.findItem(R.id.delete_all); 143 if (allCallsFragment != null && itemDeleteAll != null) { 144 // If onPrepareOptionsMenu is called before fragments are loaded, don't do anything. 145 final CallLogAdapter adapter = allCallsFragment.getAdapter(); 146 itemDeleteAll.setVisible(adapter != null && !adapter.isEmpty()); 147 } 148 return true; 149 } 150 151 @Override onOptionsItemSelected(MenuItem item)152 public boolean onOptionsItemSelected(MenuItem item) { 153 if (!isSafeToCommitTransactions()) { 154 return true; 155 } 156 157 if (item.getItemId() == android.R.id.home) { 158 PerformanceReport.recordClick(UiAction.Type.CLOSE_CALL_HISTORY_WITH_CANCEL_BUTTON); 159 final Intent intent = new Intent("com.android.dialer.main.impl.MAIN"); 160 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 161 startActivity(intent); 162 return true; 163 } else if (item.getItemId() == R.id.delete_all) { 164 ClearCallLogDialog.show(getFragmentManager()); 165 return true; 166 } 167 return super.onOptionsItemSelected(item); 168 } 169 170 @Override onPageScrolled(int position, float positionOffset, int positionOffsetPixels)171 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 172 viewPagerTabs.onPageScrolled(position, positionOffset, positionOffsetPixels); 173 } 174 175 @Override onPageSelected(int position)176 public void onPageSelected(int position) { 177 updateMissedCalls(position); 178 selectedPageIndex = position; 179 if (isResumed) { 180 sendScreenViewForChildFragment(); 181 } 182 viewPagerTabs.onPageSelected(position); 183 } 184 185 @Override onPageScrollStateChanged(int state)186 public void onPageScrollStateChanged(int state) { 187 viewPagerTabs.onPageScrollStateChanged(state); 188 } 189 sendScreenViewForChildFragment()190 private void sendScreenViewForChildFragment() { 191 Logger.get(this).logScreenView(ScreenEvent.Type.CALL_LOG_FILTER, this); 192 } 193 getRtlPosition(int position)194 private int getRtlPosition(int position) { 195 if (ViewUtil.isRtl()) { 196 return viewPagerAdapter.getCount() - 1 - position; 197 } 198 return position; 199 } 200 updateMissedCalls(int position)201 private void updateMissedCalls(int position) { 202 if (position == selectedPageIndex) { 203 return; 204 } 205 switch (getRtlPosition(position)) { 206 case TAB_INDEX_ALL: 207 if (allCallsFragment != null) { 208 allCallsFragment.markMissedCallsAsReadAndRemoveNotifications(); 209 } 210 break; 211 case TAB_INDEX_MISSED: 212 if (missedCallsFragment != null) { 213 missedCallsFragment.markMissedCallsAsReadAndRemoveNotifications(); 214 } 215 break; 216 default: 217 throw Assert.createIllegalStateFailException("Invalid position: " + position); 218 } 219 } 220 221 @Override onBackPressed()222 public void onBackPressed() { 223 PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON); 224 super.onBackPressed(); 225 } 226 227 /** Adapter for the view pager. */ 228 public class ViewPagerAdapter extends FragmentPagerAdapter { 229 ViewPagerAdapter(FragmentManager fm)230 public ViewPagerAdapter(FragmentManager fm) { 231 super(fm); 232 } 233 234 @Override getItemId(int position)235 public long getItemId(int position) { 236 return getRtlPosition(position); 237 } 238 239 @Override getItem(int position)240 public Fragment getItem(int position) { 241 switch (getRtlPosition(position)) { 242 case TAB_INDEX_ALL: 243 return new CallLogFragment( 244 CallLogQueryHandler.CALL_TYPE_ALL, true /* isCallLogActivity */); 245 case TAB_INDEX_MISSED: 246 return new CallLogFragment(Calls.MISSED_TYPE, true /* isCallLogActivity */); 247 default: 248 throw new IllegalStateException("No fragment at position " + position); 249 } 250 } 251 252 @Override instantiateItem(ViewGroup container, int position)253 public Object instantiateItem(ViewGroup container, int position) { 254 final CallLogFragment fragment = (CallLogFragment) super.instantiateItem(container, position); 255 switch (getRtlPosition(position)) { 256 case TAB_INDEX_ALL: 257 allCallsFragment = fragment; 258 break; 259 case TAB_INDEX_MISSED: 260 missedCallsFragment = fragment; 261 break; 262 default: 263 throw Assert.createIllegalStateFailException("Invalid position: " + position); 264 } 265 return fragment; 266 } 267 268 @Override getPageTitle(int position)269 public CharSequence getPageTitle(int position) { 270 return tabTitles[position]; 271 } 272 273 @Override getCount()274 public int getCount() { 275 return TAB_INDEX_COUNT; 276 } 277 } 278 279 @Override onActivityResult(int requestCode, int resultCode, Intent data)280 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 281 if (requestCode == ActivityRequestCodes.DIALTACTS_CALL_DETAILS) { 282 if (resultCode == RESULT_OK 283 && data != null 284 && data.getBooleanExtra(OldCallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) { 285 String number = data.getStringExtra(OldCallDetailsActivity.EXTRA_PHONE_NUMBER); 286 Snackbar.make(findViewById(R.id.calllog_frame), getString(R.string.ec_data_deleted), 5_000) 287 .setAction( 288 R.string.view_conversation, 289 v -> startActivity(IntentProvider.getSendSmsIntentProvider(number).getIntent(this))) 290 .setActionTextColor(getResources().getColor(R.color.dialer_snackbar_action_text_color)) 291 .show(); 292 } 293 } 294 super.onActivityResult(requestCode, resultCode, data); 295 } 296 } 297