blob: 7cb517bbdb774b487c1e2948264124e524f2e007 [file] [log] [blame]
Chiao Cheng94b10b52012-08-17 16:59:12 -07001/*
2 * Copyright (C) 2009 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
17package com.android.dialer;
18
Chiao Cheng94b10b52012-08-17 16:59:12 -070019import android.content.ContentUris;
Chiao Cheng94b10b52012-08-17 16:59:12 -070020import android.content.Context;
21import android.content.Intent;
22import android.content.res.Resources;
Chiao Cheng94b10b52012-08-17 16:59:12 -070023import android.net.Uri;
Chiao Cheng94b10b52012-08-17 16:59:12 -070024import android.os.Bundle;
Chiao Cheng94b10b52012-08-17 16:59:12 -070025import android.provider.ContactsContract.CommonDataKinds.Phone;
Nancy Chen44898ad2015-08-13 12:03:47 -070026import android.support.v7.app.AppCompatActivity;
Nancy Chene80d6222014-10-08 20:17:55 -070027import android.telecom.PhoneAccountHandle;
Andrew Lee99e8adb2014-10-02 12:27:37 -070028import android.text.BidiFormatter;
29import android.text.TextDirectionHeuristics;
Chiao Cheng94b10b52012-08-17 16:59:12 -070030import android.text.TextUtils;
Chiao Cheng94b10b52012-08-17 16:59:12 -070031import android.view.LayoutInflater;
32import android.view.Menu;
33import android.view.MenuItem;
Yorke Lee0b458972015-09-18 12:55:30 -070034import android.view.MotionEvent;
Chiao Cheng94b10b52012-08-17 16:59:12 -070035import android.view.View;
Chiao Cheng94b10b52012-08-17 16:59:12 -070036import android.widget.ListView;
Tyler Gunn18164c82014-06-09 10:20:57 -070037import android.widget.QuickContactBadge;
Chiao Cheng94b10b52012-08-17 16:59:12 -070038import android.widget.TextView;
39import android.widget.Toast;
40
Chiao Cheng35071c02012-10-15 18:36:24 -070041import com.android.contacts.common.ContactPhotoManager;
Yorke Lee56cb0ef2014-02-21 10:02:18 -080042import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
Yorke Lee0b458972015-09-18 12:55:30 -070043import com.android.contacts.common.interactions.TouchPointManager;
Chiao Cheng35071c02012-10-15 18:36:24 -070044import com.android.contacts.common.GeoUtil;
Brian Attwell82043242015-02-03 14:13:58 -080045import com.android.contacts.common.CallUtil;
Tyler Gunn18b4a2e2015-08-05 08:18:37 -070046import com.android.contacts.common.util.UriUtils;
Chiao Cheng94b10b52012-08-17 16:59:12 -070047import com.android.dialer.calllog.CallDetailHistoryAdapter;
Andrew Lee7c461dc2015-05-15 10:18:45 -070048import com.android.dialer.calllog.CallLogAsyncTaskUtil.CallLogAsyncTaskListener;
49import com.android.dialer.calllog.CallLogAsyncTaskUtil;
Chiao Cheng94b10b52012-08-17 16:59:12 -070050import com.android.dialer.calllog.CallTypeHelper;
Chiao Cheng94b10b52012-08-17 16:59:12 -070051import com.android.dialer.calllog.ContactInfoHelper;
Nancy Chenb2eebaf2014-07-21 13:41:36 -070052import com.android.dialer.calllog.PhoneAccountUtils;
Yorke Leee3a2d132015-09-14 16:52:08 -070053import com.android.dialer.util.IntentUtil.CallIntentBuilder;
Andrew Leed3f6a6c2015-06-25 16:53:56 -070054import com.android.dialer.util.PhoneNumberUtil;
Yorke Lee4aece952015-05-02 22:22:54 -070055import com.android.dialer.util.TelecomUtil;
Yorke Leec8d6e162015-09-14 18:43:27 -070056import com.android.incallui.Call.LogState;
Chiao Cheng94b10b52012-08-17 16:59:12 -070057
Chiao Cheng94b10b52012-08-17 16:59:12 -070058/**
59 * Displays the details of a specific call log entry.
60 * <p>
61 * This activity can be either started with the URI of a single call log entry, or with the
62 * {@link #EXTRA_CALL_LOG_IDS} extra to specify a group of call log entries.
63 */
Nancy Chen44898ad2015-08-13 12:03:47 -070064public class CallDetailActivity extends AppCompatActivity
Andrew Lee2f05af32015-06-09 15:59:47 -070065 implements MenuItem.OnMenuItemClickListener {
Chiao Cheng94b10b52012-08-17 16:59:12 -070066 private static final String TAG = "CallDetail";
67
Andrew Lee7c461dc2015-05-15 10:18:45 -070068 /** A long array extra containing ids of call log entries to display. */
Chiao Cheng94b10b52012-08-17 16:59:12 -070069 public static final String EXTRA_CALL_LOG_IDS = "EXTRA_CALL_LOG_IDS";
70 /** If we are started with a voicemail, we'll find the uri to play with this extra. */
71 public static final String EXTRA_VOICEMAIL_URI = "EXTRA_VOICEMAIL_URI";
Chiao Cheng94b10b52012-08-17 16:59:12 -070072 /** If the activity was triggered from a notification. */
73 public static final String EXTRA_FROM_NOTIFICATION = "EXTRA_FROM_NOTIFICATION";
74
Yorke Lee8cd94232014-07-23 14:05:31 -070075 public static final String VOICEMAIL_FRAGMENT_TAG = "voicemail_fragment";
76
Andrew Lee7c461dc2015-05-15 10:18:45 -070077 private CallLogAsyncTaskListener mCallLogAsyncTaskListener = new CallLogAsyncTaskListener() {
78 @Override
79 public void onDeleteCall() {
80 finish();
81 }
82
83 @Override
84 public void onDeleteVoicemail() {
85 finish();
86 }
87
88 @Override
89 public void onGetCallDetails(PhoneCallDetails[] details) {
Andrew Lee7c461dc2015-05-15 10:18:45 -070090 if (details == null) {
91 // Somewhere went wrong: we're going to bail out and show error to users.
Andrew Leee177fe62015-06-05 13:01:09 -070092 Toast.makeText(mContext, R.string.toast_call_detail_error,
Andrew Lee7c461dc2015-05-15 10:18:45 -070093 Toast.LENGTH_SHORT).show();
94 finish();
95 return;
96 }
97
98 // We know that all calls are from the same number and the same contact, so pick the
99 // first.
100 PhoneCallDetails firstDetails = details[0];
101 mNumber = TextUtils.isEmpty(firstDetails.number) ?
102 null : firstDetails.number.toString();
103 final int numberPresentation = firstDetails.numberPresentation;
104 final Uri contactUri = firstDetails.contactUri;
105 final Uri photoUri = firstDetails.photoUri;
106 final PhoneAccountHandle accountHandle = firstDetails.accountHandle;
107
108 // Cache the details about the phone number.
109 final boolean canPlaceCallsTo =
Andrew Leed3f6a6c2015-06-25 16:53:56 -0700110 PhoneNumberUtil.canPlaceCallsTo(mNumber, numberPresentation);
Andrew Leee177fe62015-06-05 13:01:09 -0700111 mIsVoicemailNumber =
Andrew Leed3f6a6c2015-06-25 16:53:56 -0700112 PhoneNumberUtil.isVoicemailNumber(mContext, accountHandle, mNumber);
113 final boolean isSipNumber = PhoneNumberUtil.isSipNumber(mNumber);
Andrew Lee7c461dc2015-05-15 10:18:45 -0700114
115 final CharSequence callLocationOrType = getNumberTypeOrLocation(firstDetails);
116
117 final CharSequence displayNumber = firstDetails.displayNumber;
118 final String displayNumberStr = mBidiFormatter.unicodeWrap(
119 displayNumber.toString(), TextDirectionHeuristics.LTR);
120
121 if (!TextUtils.isEmpty(firstDetails.name)) {
122 mCallerName.setText(firstDetails.name);
123 mCallerNumber.setText(callLocationOrType + " " + displayNumberStr);
124 } else {
125 mCallerName.setText(displayNumberStr);
126 if (!TextUtils.isEmpty(callLocationOrType)) {
127 mCallerNumber.setText(callLocationOrType);
128 mCallerNumber.setVisibility(View.VISIBLE);
129 } else {
130 mCallerNumber.setVisibility(View.GONE);
131 }
132 }
133
Andrew Leee177fe62015-06-05 13:01:09 -0700134 mCallButton.setVisibility(canPlaceCallsTo ? View.VISIBLE : View.GONE);
135
136 String accountLabel = PhoneAccountUtils.getAccountLabel(mContext, accountHandle);
Andrew Lee7c461dc2015-05-15 10:18:45 -0700137 if (!TextUtils.isEmpty(accountLabel)) {
138 mAccountLabel.setText(accountLabel);
139 mAccountLabel.setVisibility(View.VISIBLE);
140 } else {
141 mAccountLabel.setVisibility(View.GONE);
142 }
143
144 mHasEditNumberBeforeCallOption =
Andrew Leee177fe62015-06-05 13:01:09 -0700145 canPlaceCallsTo && !isSipNumber && !mIsVoicemailNumber;
Andrew Lee2f05af32015-06-09 15:59:47 -0700146 mHasReportMenuOption = mContactInfoHelper.canReportAsInvalid(
147 firstDetails.sourceType, firstDetails.objectId);
Andrew Lee7c461dc2015-05-15 10:18:45 -0700148 invalidateOptionsMenu();
149
150 ListView historyList = (ListView) findViewById(R.id.history);
151 historyList.setAdapter(
Andrew Leee177fe62015-06-05 13:01:09 -0700152 new CallDetailHistoryAdapter(mContext, mInflater, mCallTypeHelper, details));
Andrew Lee7c461dc2015-05-15 10:18:45 -0700153
154 String lookupKey = contactUri == null ? null
Tyler Gunn18b4a2e2015-08-05 08:18:37 -0700155 : UriUtils.getLookupKeyFromUri(contactUri);
Andrew Lee7c461dc2015-05-15 10:18:45 -0700156
157 final boolean isBusiness = mContactInfoHelper.isBusiness(firstDetails.sourceType);
158
159 final int contactType =
Andrew Leee177fe62015-06-05 13:01:09 -0700160 mIsVoicemailNumber ? ContactPhotoManager.TYPE_VOICEMAIL :
Andrew Lee7c461dc2015-05-15 10:18:45 -0700161 isBusiness ? ContactPhotoManager.TYPE_BUSINESS :
162 ContactPhotoManager.TYPE_DEFAULT;
163
164 String nameForDefaultImage;
165 if (TextUtils.isEmpty(firstDetails.name)) {
166 nameForDefaultImage = firstDetails.displayNumber;
167 } else {
168 nameForDefaultImage = firstDetails.name.toString();
169 }
170
171 loadContactPhotos(
172 contactUri, photoUri, nameForDefaultImage, lookupKey, contactType);
173 findViewById(R.id.call_detail).setVisibility(View.VISIBLE);
174 }
175
176 /**
177 * Determines the location geocode text for a call, or the phone number type
178 * (if available).
179 *
180 * @param details The call details.
181 * @return The phone number type or location.
182 */
183 private CharSequence getNumberTypeOrLocation(PhoneCallDetails details) {
184 if (!TextUtils.isEmpty(details.name)) {
185 return Phone.getTypeLabel(mResources, details.numberType,
186 details.numberLabel);
187 } else {
188 return details.geocode;
189 }
190 }
191 };
192
Andrew Leee177fe62015-06-05 13:01:09 -0700193 private Context mContext;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700194 private CallTypeHelper mCallTypeHelper;
Tyler Gunn18164c82014-06-09 10:20:57 -0700195 private QuickContactBadge mQuickContactBadge;
196 private TextView mCallerName;
197 private TextView mCallerNumber;
Nancy Chen19702632014-07-25 13:23:16 -0700198 private TextView mAccountLabel;
Andrew Leee177fe62015-06-05 13:01:09 -0700199 private View mCallButton;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700200 private ContactInfoHelper mContactInfoHelper;
201
Andrew Lee2f05af32015-06-09 15:59:47 -0700202 protected String mNumber;
Andrew Leee177fe62015-06-05 13:01:09 -0700203 private boolean mIsVoicemailNumber;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700204 private String mDefaultCountryIso;
205
206 /* package */ LayoutInflater mInflater;
207 /* package */ Resources mResources;
208 /** Helper to load contact photos. */
209 private ContactPhotoManager mContactPhotoManager;
Andrew Leec1167e92015-05-18 11:27:54 -0700210
Yorke Lee257b6f22014-07-31 14:16:44 -0700211 private Uri mVoicemailUri;
Andrew Lee99e8adb2014-10-02 12:27:37 -0700212 private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
Chiao Cheng94b10b52012-08-17 16:59:12 -0700213
214 /** Whether we should show "edit number before call" in the options menu. */
215 private boolean mHasEditNumberBeforeCallOption;
Andrew Lee2f05af32015-06-09 15:59:47 -0700216 private boolean mHasReportMenuOption;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700217
Chiao Cheng94b10b52012-08-17 16:59:12 -0700218 @Override
219 protected void onCreate(Bundle icicle) {
220 super.onCreate(icicle);
221
Andrew Leee177fe62015-06-05 13:01:09 -0700222 mContext = this;
223
Chiao Cheng94b10b52012-08-17 16:59:12 -0700224 setContentView(R.layout.call_detail);
225
Chiao Cheng94b10b52012-08-17 16:59:12 -0700226 mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
227 mResources = getResources();
228
229 mCallTypeHelper = new CallTypeHelper(getResources());
Yorke Lee257b6f22014-07-31 14:16:44 -0700230
231 mVoicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
232
Tyler Gunn18164c82014-06-09 10:20:57 -0700233 mQuickContactBadge = (QuickContactBadge) findViewById(R.id.quick_contact_photo);
234 mQuickContactBadge.setOverlay(null);
Brian Attwell74eb4ec2015-02-25 22:31:22 -0800235 mQuickContactBadge.setPrioritizedMimeType(Phone.CONTENT_ITEM_TYPE);
Tyler Gunn18164c82014-06-09 10:20:57 -0700236 mCallerName = (TextView) findViewById(R.id.caller_name);
237 mCallerNumber = (TextView) findViewById(R.id.caller_number);
Nancy Chen19702632014-07-25 13:23:16 -0700238 mAccountLabel = (TextView) findViewById(R.id.phone_account_label);
Chiao Cheng35071c02012-10-15 18:36:24 -0700239 mDefaultCountryIso = GeoUtil.getCurrentCountryIso(this);
Chiao Cheng94b10b52012-08-17 16:59:12 -0700240 mContactPhotoManager = ContactPhotoManager.getInstance(this);
Yorke Lee71513982015-02-25 20:23:53 -0800241
Yorke Leee3a2d132015-09-14 16:52:08 -0700242 mCallButton = findViewById(R.id.call_back_button);
Andrew Leee177fe62015-06-05 13:01:09 -0700243 mCallButton.setOnClickListener(new View.OnClickListener() {
244 @Override
245 public void onClick(View view) {
Yorke Leec8d6e162015-09-14 18:43:27 -0700246 mContext.startActivity(
247 new CallIntentBuilder(mNumber)
248 .setCallInitiationType(LogState.INITIATION_CALL_DETAILS)
249 .build());
Andrew Leee177fe62015-06-05 13:01:09 -0700250 }
251 });
252
Chiao Cheng35071c02012-10-15 18:36:24 -0700253 mContactInfoHelper = new ContactInfoHelper(this, GeoUtil.getCurrentCountryIso(this));
Nancy Chen44898ad2015-08-13 12:03:47 -0700254 getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Yorke Lee257b6f22014-07-31 14:16:44 -0700255
Chiao Cheng94b10b52012-08-17 16:59:12 -0700256 if (getIntent().getBooleanExtra(EXTRA_FROM_NOTIFICATION, false)) {
257 closeSystemDialogs();
258 }
259 }
260
261 @Override
262 public void onResume() {
263 super.onResume();
Andrew Lee2f05af32015-06-09 15:59:47 -0700264 getCallDetails();
265 }
Andrew Lee7c461dc2015-05-15 10:18:45 -0700266
Yorke Lee0b458972015-09-18 12:55:30 -0700267 @Override
268 public boolean dispatchTouchEvent(MotionEvent ev) {
269 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
270 TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY());
271 }
272 return super.dispatchTouchEvent(ev);
273 }
274
Andrew Lee2f05af32015-06-09 15:59:47 -0700275 public void getCallDetails() {
Andrew Lee7c461dc2015-05-15 10:18:45 -0700276 CallLogAsyncTaskUtil.getCallDetails(this, getCallLogEntryUris(), mCallLogAsyncTaskListener);
Chiao Cheng94b10b52012-08-17 16:59:12 -0700277 }
278
Chiao Cheng94b10b52012-08-17 16:59:12 -0700279 private boolean hasVoicemail() {
Yorke Lee257b6f22014-07-31 14:16:44 -0700280 return mVoicemailUri != null;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700281 }
282
Chiao Cheng94b10b52012-08-17 16:59:12 -0700283 /**
284 * Returns the list of URIs to show.
285 * <p>
286 * There are two ways the URIs can be provided to the activity: as the data on the intent, or as
287 * a list of ids in the call log added as an extra on the URI.
288 * <p>
289 * If both are available, the data on the intent takes precedence.
290 */
291 private Uri[] getCallLogEntryUris() {
Jay Shrauner757bdd32014-05-28 10:13:40 -0700292 final Uri uri = getIntent().getData();
Chiao Cheng94b10b52012-08-17 16:59:12 -0700293 if (uri != null) {
294 // If there is a data on the intent, it takes precedence over the extra.
295 return new Uri[]{ uri };
296 }
Jay Shrauner757bdd32014-05-28 10:13:40 -0700297 final long[] ids = getIntent().getLongArrayExtra(EXTRA_CALL_LOG_IDS);
298 final int numIds = ids == null ? 0 : ids.length;
299 final Uri[] uris = new Uri[numIds];
300 for (int index = 0; index < numIds; ++index) {
Yorke Lee4aece952015-05-02 22:22:54 -0700301 uris[index] = ContentUris.withAppendedId(
302 TelecomUtil.getCallLogUri(CallDetailActivity.this), ids[index]);
Chiao Cheng94b10b52012-08-17 16:59:12 -0700303 }
304 return uris;
305 }
306
Chiao Cheng94b10b52012-08-17 16:59:12 -0700307 /** Load the contact photos and places them in the corresponding views. */
Tyler Gunn18164c82014-06-09 10:20:57 -0700308 private void loadContactPhotos(Uri contactUri, Uri photoUri, String displayName,
309 String lookupKey, int contactType) {
310
Yorke Lee56cb0ef2014-02-21 10:02:18 -0800311 final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
Tyler Gunn18164c82014-06-09 10:20:57 -0700312 contactType, true /* isCircular */);
313
314 mQuickContactBadge.assignContactUri(contactUri);
315 mQuickContactBadge.setContentDescription(
316 mResources.getString(R.string.description_contact_details, displayName));
317
318 mContactPhotoManager.loadDirectoryPhoto(mQuickContactBadge, photoUri,
319 false /* darkTheme */, true /* isCircular */, request);
Chiao Cheng94b10b52012-08-17 16:59:12 -0700320 }
321
Chiao Cheng94b10b52012-08-17 16:59:12 -0700322 @Override
323 public boolean onCreateOptionsMenu(Menu menu) {
Andrew Lee11a73502015-09-30 18:24:48 -0700324 final MenuItem deleteMenuItem = menu.add(
325 Menu.NONE,
326 R.id.call_detail_delete_menu_item,
327 Menu.NONE,
328 R.string.call_details_delete);
329 deleteMenuItem.setIcon(R.drawable.ic_delete_24dp);
330 deleteMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
331 deleteMenuItem.setOnMenuItemClickListener(this);
332
Chiao Cheng94b10b52012-08-17 16:59:12 -0700333 getMenuInflater().inflate(R.menu.call_details_options, menu);
334 return super.onCreateOptionsMenu(menu);
335 }
336
337 @Override
338 public boolean onPrepareOptionsMenu(Menu menu) {
Andrew Lee2f05af32015-06-09 15:59:47 -0700339 menu.findItem(R.id.menu_edit_number_before_call)
340 .setVisible(mHasEditNumberBeforeCallOption)
341 .setOnMenuItemClickListener(this);
Andrew Lee2f05af32015-06-09 15:59:47 -0700342 menu.findItem(R.id.menu_report)
343 .setVisible(mHasReportMenuOption)
344 .setOnMenuItemClickListener(this);
Chiao Cheng94b10b52012-08-17 16:59:12 -0700345 return super.onPrepareOptionsMenu(menu);
346 }
347
Andrew Lee2f05af32015-06-09 15:59:47 -0700348 @Override
349 public boolean onMenuItemClick(MenuItem item) {
350 switch (item.getItemId()) {
Andrew Lee11a73502015-09-30 18:24:48 -0700351 case R.id.call_detail_delete_menu_item:
352 if (hasVoicemail()) {
353 CallLogAsyncTaskUtil.deleteVoicemail(
354 this, mVoicemailUri, mCallLogAsyncTaskListener);
355 } else {
356 final StringBuilder callIds = new StringBuilder();
357 for (Uri callUri : getCallLogEntryUris()) {
358 if (callIds.length() != 0) {
359 callIds.append(",");
360 }
361 callIds.append(ContentUris.parseId(callUri));
Andrew Lee2f05af32015-06-09 15:59:47 -0700362 }
Andrew Lee11a73502015-09-30 18:24:48 -0700363 CallLogAsyncTaskUtil.deleteCalls(
364 this, callIds.toString(), mCallLogAsyncTaskListener);
Andrew Lee2f05af32015-06-09 15:59:47 -0700365 }
Andrew Lee2f05af32015-06-09 15:59:47 -0700366 break;
367 case R.id.menu_edit_number_before_call:
368 startActivity(new Intent(Intent.ACTION_DIAL, CallUtil.getCallUri(mNumber)));
369 break;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700370 }
Andrew Lee2f05af32015-06-09 15:59:47 -0700371 return true;
Chiao Cheng94b10b52012-08-17 16:59:12 -0700372 }
373
Chiao Cheng94b10b52012-08-17 16:59:12 -0700374 private void closeSystemDialogs() {
375 sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
376 }
Chiao Cheng94b10b52012-08-17 16:59:12 -0700377}