Home | History | Annotate | Download | only in calllog
      1 /*
      2  * Copyright (C) 2011 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 
     17 package com.android.dialer.calllog;
     18 
     19 import android.content.res.Resources;
     20 import android.provider.CallLog.Calls;
     21 import android.text.SpannableStringBuilder;
     22 import android.text.TextUtils;
     23 import android.util.Log;
     24 
     25 import com.android.dialer.PhoneCallDetails;
     26 import com.android.dialer.util.AppCompatConstants;
     27 import com.android.dialer.R;
     28 import com.android.dialer.calllog.calllogcache.CallLogCache;
     29 
     30 /**
     31  * Helper class to fill in the views of a call log entry.
     32  */
     33 /* package */class CallLogListItemHelper {
     34     private static final String TAG = "CallLogListItemHelper";
     35 
     36     /** Helper for populating the details of a phone call. */
     37     private final PhoneCallDetailsHelper mPhoneCallDetailsHelper;
     38     /** Resources to look up strings. */
     39     private final Resources mResources;
     40     private final CallLogCache mCallLogCache;
     41 
     42     /**
     43      * Creates a new helper instance.
     44      *
     45      * @param phoneCallDetailsHelper used to set the details of a phone call
     46      * @param resources The object from which resources can be retrieved
     47      * @param callLogCache A cache for values retrieved from telecom/telephony
     48      */
     49     public CallLogListItemHelper(
     50             PhoneCallDetailsHelper phoneCallDetailsHelper,
     51             Resources resources,
     52             CallLogCache callLogCache) {
     53         mPhoneCallDetailsHelper = phoneCallDetailsHelper;
     54         mResources = resources;
     55         mCallLogCache = callLogCache;
     56     }
     57 
     58     /**
     59      * Sets the name, label, and number for a contact.
     60      *
     61      * @param views the views to populate
     62      * @param details the details of a phone call needed to fill in the data
     63      */
     64     public void setPhoneCallDetails(
     65             CallLogListItemViewHolder views,
     66             PhoneCallDetails details) {
     67         mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details);
     68 
     69         // Set the accessibility text for the contact badge
     70         views.quickContactView.setContentDescription(getContactBadgeDescription(details));
     71 
     72         // Set the primary action accessibility description
     73         views.primaryActionView.setContentDescription(getCallDescription(details));
     74 
     75         // Cache name or number of caller.  Used when setting the content descriptions of buttons
     76         // when the actions ViewStub is inflated.
     77         views.nameOrNumber = getNameOrNumber(details);
     78 
     79         // The call type or Location associated with the call. Use when setting text for a
     80         // voicemail log's call button
     81         views.callTypeOrLocation = mPhoneCallDetailsHelper.getCallTypeOrLocation(details);
     82 
     83         // Cache country iso. Used for number filtering.
     84         views.countryIso = details.countryIso;
     85     }
     86 
     87     /**
     88      * Sets the accessibility descriptions for the action buttons in the action button ViewStub.
     89      *
     90      * @param views The views associated with the current call log entry.
     91      */
     92     public void setActionContentDescriptions(CallLogListItemViewHolder views) {
     93         if (views.nameOrNumber == null) {
     94             Log.e(TAG, "setActionContentDescriptions; name or number is null.");
     95         }
     96 
     97         // Calling expandTemplate with a null parameter will cause a NullPointerException.
     98         // Although we don't expect a null name or number, it is best to protect against it.
     99         CharSequence nameOrNumber = views.nameOrNumber == null ? "" : views.nameOrNumber;
    100 
    101         views.videoCallButtonView.setContentDescription(
    102                 TextUtils.expandTemplate(
    103                         mResources.getString(R.string.description_video_call_action),
    104                         nameOrNumber));
    105 
    106         views.createNewContactButtonView.setContentDescription(
    107                 TextUtils.expandTemplate(
    108                         mResources.getString(R.string.description_create_new_contact_action),
    109                         nameOrNumber));
    110 
    111         views.addToExistingContactButtonView.setContentDescription(
    112                 TextUtils.expandTemplate(
    113                         mResources.getString(R.string.description_add_to_existing_contact_action),
    114                         nameOrNumber));
    115 
    116         views.detailsButtonView.setContentDescription(
    117                 TextUtils.expandTemplate(
    118                         mResources.getString(R.string.description_details_action), nameOrNumber));
    119     }
    120 
    121     /**
    122      * Returns the accessibility description for the contact badge for a call log entry.
    123      *
    124      * @param details Details of call.
    125      * @return Accessibility description.
    126      */
    127     private CharSequence getContactBadgeDescription(PhoneCallDetails details) {
    128         return mResources.getString(R.string.description_contact_details, getNameOrNumber(details));
    129     }
    130 
    131     /**
    132      * Returns the accessibility description of the "return call/call" action for a call log
    133      * entry.
    134      * Accessibility text is a combination of:
    135      * {Voicemail Prefix}. {Number of Calls}. {Caller information} {Phone Account}.
    136      * If most recent call is a voicemail, {Voicemail Prefix} is "New Voicemail.", otherwise "".
    137      *
    138      * If more than one call for the caller, {Number of Calls} is:
    139      * "{number of calls} calls.", otherwise "".
    140      *
    141      * The {Caller Information} references the most recent call associated with the caller.
    142      * For incoming calls:
    143      * If missed call:  Missed call from {Name/Number} {Call Type} {Call Time}.
    144      * If answered call: Answered call from {Name/Number} {Call Type} {Call Time}.
    145      *
    146      * For outgoing calls:
    147      * If outgoing:  Call to {Name/Number] {Call Type} {Call Time}.
    148      *
    149      * Where:
    150      * {Name/Number} is the name or number of the caller (as shown in call log).
    151      * {Call type} is the contact phone number type (eg mobile) or location.
    152      * {Call Time} is the time since the last call for the contact occurred.
    153      *
    154      * The {Phone Account} refers to the account/SIM through which the call was placed or received
    155      * in multi-SIM devices.
    156      *
    157      * Examples:
    158      * 3 calls.  New Voicemail.  Missed call from Joe Smith mobile 2 hours ago on SIM 1.
    159      *
    160      * 2 calls.  Answered call from John Doe mobile 1 hour ago.
    161      *
    162      * @param context The application context.
    163      * @param details Details of call.
    164      * @return Return call action description.
    165      */
    166     public CharSequence getCallDescription(PhoneCallDetails details) {
    167         int lastCallType = getLastCallType(details.callTypes);
    168 
    169         // Get the name or number of the caller.
    170         final CharSequence nameOrNumber = getNameOrNumber(details);
    171 
    172         // Get the call type or location of the caller; null if not applicable
    173         final CharSequence typeOrLocation = mPhoneCallDetailsHelper.getCallTypeOrLocation(details);
    174 
    175         // Get the time/date of the call
    176         final CharSequence timeOfCall = mPhoneCallDetailsHelper.getCallDate(details);
    177 
    178         SpannableStringBuilder callDescription = new SpannableStringBuilder();
    179 
    180         // Add number of calls if more than one.
    181         if (details.callTypes.length > 1) {
    182             callDescription.append(mResources.getString(R.string.description_num_calls,
    183                     details.callTypes.length));
    184         }
    185 
    186         // If call had video capabilities, add the "Video Call" string.
    187         if ((details.features & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) {
    188             callDescription.append(mResources.getString(R.string.description_video_call));
    189         }
    190 
    191         String accountLabel = mCallLogCache.getAccountLabel(details.accountHandle);
    192         CharSequence onAccountLabel = PhoneCallDetails.createAccountLabelDescription(mResources,
    193                 details.viaNumber, accountLabel);
    194 
    195         int stringID = getCallDescriptionStringID(details.callTypes, details.isRead);
    196         callDescription.append(
    197                 TextUtils.expandTemplate(
    198                         mResources.getString(stringID),
    199                         nameOrNumber,
    200                         typeOrLocation == null ? "" : typeOrLocation,
    201                         timeOfCall,
    202                         onAccountLabel));
    203 
    204         return callDescription;
    205     }
    206 
    207     /**
    208      * Determine the appropriate string ID to describe a call for accessibility purposes.
    209      *
    210      * @param callTypes The type of call corresponding to this entry or multiple if this entry
    211      * represents multiple calls grouped together.
    212      * @param isRead If the entry is a voicemail, {@code true} if the voicemail is read.
    213      * @return String resource ID to use.
    214      */
    215     public int getCallDescriptionStringID(int[] callTypes, boolean isRead) {
    216         int lastCallType = getLastCallType(callTypes);
    217         int stringID;
    218 
    219         if (lastCallType == AppCompatConstants.CALLS_MISSED_TYPE) {
    220             //Message: Missed call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
    221             //<PhoneAccount>.
    222             stringID = R.string.description_incoming_missed_call;
    223         } else if (lastCallType == AppCompatConstants.CALLS_INCOMING_TYPE) {
    224             //Message: Answered call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
    225             //<PhoneAccount>.
    226             stringID = R.string.description_incoming_answered_call;
    227         } else if (lastCallType == AppCompatConstants.CALLS_VOICEMAIL_TYPE) {
    228             //Message: (Unread) [V/v]oicemail from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
    229             //<PhoneAccount>.
    230             stringID = isRead ? R.string.description_read_voicemail
    231                 : R.string.description_unread_voicemail;
    232         } else {
    233             //Message: Call to <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>, <PhoneAccount>.
    234             stringID = R.string.description_outgoing_call;
    235         }
    236         return stringID;
    237     }
    238 
    239     /**
    240      * Determine the call type for the most recent call.
    241      * @param callTypes Call types to check.
    242      * @return Call type.
    243      */
    244     private int getLastCallType(int[] callTypes) {
    245         if (callTypes.length > 0) {
    246             return callTypes[0];
    247         } else {
    248             return Calls.MISSED_TYPE;
    249         }
    250     }
    251 
    252     /**
    253      * Return the name or number of the caller specified by the details.
    254      * @param details Call details
    255      * @return the name (if known) of the caller, otherwise the formatted number.
    256      */
    257     private CharSequence getNameOrNumber(PhoneCallDetails details) {
    258         final CharSequence recipient;
    259         if (!TextUtils.isEmpty(details.getPreferredName())) {
    260             recipient = details.getPreferredName();
    261         } else {
    262             recipient = details.displayNumber + details.postDialDigits;
    263         }
    264         return recipient;
    265     }
    266 }
    267