/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.dialer.calllogutils; import android.content.Context; import android.provider.CallLog.Calls; import android.support.annotation.PluralsRes; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.dialer.calllog.model.CoalescedRow; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.time.Clock; import com.google.common.collect.Collections2; import java.util.List; /** Builds descriptions of call log entries for accessibility users. */ public final class CallLogEntryDescriptions { private CallLogEntryDescriptions() {} /** * Builds the content description for a call log entry. * *

The description is of format
* {primary description}, {secondary description}, {phone account description}. * *

* *

An example of the full description can be:
* "2 calls, the latest is an answered call from Jane Smith, mobile, 11 minutes ago, on SIM 1, via * 6502531234". */ public static CharSequence buildDescriptionForEntry( Context context, Clock clock, CoalescedRow row) { // Build the primary description. // Examples: // (1) For an entry containing only 1 call: // "1 missed call from James Smith". // (2) For entries containing multiple calls: // "2 calls, the latest is a missed call from Jame Smith". CharSequence primaryDescription = TextUtils.expandTemplate( context .getResources() .getQuantityString( getPrimaryDescriptionResIdForCallType(row), row.getCoalescedIds().getCoalescedIdCount()), String.valueOf(row.getCoalescedIds().getCoalescedIdCount()), CallLogEntryText.buildPrimaryText(context, row)); // Build the secondary description. // An example: "mobile, 11 minutes ago". CharSequence secondaryDescription = joinSecondaryTextComponents( CallLogEntryText.buildSecondaryTextListForEntries( context, clock, row, /* abbreviateDateTime = */ false)); // Build the phone account description. // Note that this description can be an empty string. CharSequence phoneAccountDescription = buildPhoneAccountDescription(context, row); return TextUtils.isEmpty(phoneAccountDescription) ? TextUtils.expandTemplate( context .getResources() .getText( R.string.a11y_new_call_log_entry_full_description_without_phone_account_info), primaryDescription, secondaryDescription) : TextUtils.expandTemplate( context .getResources() .getText(R.string.a11y_new_call_log_entry_full_description_with_phone_account_info), primaryDescription, secondaryDescription, phoneAccountDescription); } private static @PluralsRes int getPrimaryDescriptionResIdForCallType(CoalescedRow row) { switch (row.getCallType()) { case Calls.INCOMING_TYPE: case Calls.ANSWERED_EXTERNALLY_TYPE: return R.plurals.a11y_new_call_log_entry_answered_call; case Calls.OUTGOING_TYPE: return R.plurals.a11y_new_call_log_entry_outgoing_call; case Calls.MISSED_TYPE: return R.plurals.a11y_new_call_log_entry_missed_call; case Calls.VOICEMAIL_TYPE: throw new IllegalStateException("Voicemails not expected in call log"); case Calls.BLOCKED_TYPE: return R.plurals.a11y_new_call_log_entry_blocked_call; default: // It is possible for users to end up with calls with unknown call types in their // call history, possibly due to 3rd party call log implementations (e.g. to // distinguish between rejected and missed calls). Instead of crashing, just // assume that all unknown call types are missed calls. return R.plurals.a11y_new_call_log_entry_missed_call; } } private static CharSequence buildPhoneAccountDescription(Context context, CoalescedRow row) { PhoneAccountHandle phoneAccountHandle = TelecomUtil.composePhoneAccountHandle( row.getPhoneAccountComponentName(), row.getPhoneAccountId()); if (phoneAccountHandle == null) { return ""; } String phoneAccountLabel = PhoneAccountUtils.getAccountLabel(context, phoneAccountHandle); if (TextUtils.isEmpty(phoneAccountLabel)) { return ""; } if (TextUtils.isEmpty(row.getNumber().getNormalizedNumber())) { return ""; } return TextUtils.expandTemplate( context.getResources().getText(R.string.a11y_new_call_log_entry_phone_account), phoneAccountLabel, PhoneNumberUtils.createTtsSpannable(row.getNumber().getNormalizedNumber())); } private static CharSequence joinSecondaryTextComponents(List components) { return TextUtils.join( ", ", Collections2.filter(components, (text) -> !TextUtils.isEmpty(text))); } }