CallEntryFormatter.java revision d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9
1/*
2 * Copyright (C) 2017 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.calllogutils;
18
19import android.content.Context;
20import android.icu.lang.UCharacter;
21import android.icu.text.BreakIterator;
22import android.os.Build.VERSION;
23import android.os.Build.VERSION_CODES;
24import android.text.format.DateUtils;
25import android.text.format.Formatter;
26import com.android.dialer.util.DialerUtils;
27import java.util.ArrayList;
28import java.util.List;
29import java.util.Locale;
30
31/** Utility class for formatting data and data usage in call log entries. */
32public class CallEntryFormatter {
33
34  /**
35   * Formats the provided date into a value suitable for display in the current locale.
36   *
37   * <p>For example, returns a string like "Wednesday, May 25, 2016, 8:02PM" or "Chorshanba, 2016
38   * may 25,20:02".
39   *
40   * <p>For pre-N devices, the returned value may not start with a capital if the local convention
41   * is to not capitalize day names. On N+ devices, the returned value is always capitalized.
42   */
43  public static CharSequence formatDate(Context context, long callDateMillis) {
44    CharSequence dateValue =
45        DateUtils.formatDateRange(
46            context,
47            callDateMillis /* startDate */,
48            callDateMillis /* endDate */,
49            DateUtils.FORMAT_SHOW_TIME
50                | DateUtils.FORMAT_SHOW_DATE
51                | DateUtils.FORMAT_SHOW_WEEKDAY
52                | DateUtils.FORMAT_SHOW_YEAR);
53
54    // We want the beginning of the date string to be capitalized, even if the word at the beginning
55    // of the string is not usually capitalized. For example, "Wednesdsay" in Uzbek is "chorshanba”
56    // (not capitalized). To handle this issue we apply title casing to the start of the sentence so
57    // that "chorshanba, 2016 may 25,20:02" becomes "Chorshanba, 2016 may 25,20:02".
58    //
59    // The ICU library was not available in Android until N, so we can only do this in N+ devices.
60    // Pre-N devices will still see incorrect capitalization in some languages.
61    if (VERSION.SDK_INT < VERSION_CODES.N) {
62      return dateValue;
63    }
64
65    // Using the ICU library is safer than just applying toUpperCase() on the first letter of the
66    // word because in some languages, there can be multiple starting characters which should be
67    // upper-cased together. For example in Dutch "ij" is a digraph in which both letters should be
68    // capitalized together.
69
70    // TITLECASE_NO_LOWERCASE is necessary so that things that are already capitalized like the
71    // month ("May") are not lower-cased as part of the conversion.
72    return UCharacter.toTitleCase(
73        Locale.getDefault(),
74        dateValue.toString(),
75        BreakIterator.getSentenceInstance(),
76        UCharacter.TITLECASE_NO_LOWERCASE);
77  }
78
79  private static CharSequence formatDuration(Context context, long elapsedSeconds) {
80    long minutes = 0;
81    long seconds = 0;
82
83    if (elapsedSeconds >= 60) {
84      minutes = elapsedSeconds / 60;
85      elapsedSeconds -= minutes * 60;
86      seconds = elapsedSeconds;
87      return context.getString(R.string.call_details_duration_format, minutes, seconds);
88    } else {
89      seconds = elapsedSeconds;
90      return context.getString(R.string.call_details_short_duration_format, seconds);
91    }
92  }
93
94  /**
95   * Formats a string containing the call duration and the data usage (if specified).
96   *
97   * @param elapsedSeconds Total elapsed seconds.
98   * @param dataUsage Data usage in bytes, or null if not specified.
99   * @return String containing call duration and data usage.
100   */
101  public static CharSequence formatDurationAndDataUsage(
102      Context context, long elapsedSeconds, Long dataUsage) {
103    CharSequence duration = formatDuration(context, elapsedSeconds);
104    List<CharSequence> durationItems = new ArrayList<>();
105    if (dataUsage != null) {
106      durationItems.add(duration);
107      durationItems.add(Formatter.formatShortFileSize(context, dataUsage));
108      return DialerUtils.join(durationItems);
109    } else {
110      return duration;
111    }
112  }
113}
114