diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-01-22 21:12:49 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-01-22 21:12:49 +0000 |
commit | e5a20898faa4c66758a30d12e9245f15d6685a37 (patch) | |
tree | 14dd875eb4e6aab3c01ce710cce31fb027815379 /java | |
parent | b762f4797502270f9c05e2f1774b6f06f917171f (diff) | |
parent | 5680b01ecb566e60a63c3a3362ec31f912cef692 (diff) |
Merge changes I84b69953,Ic996a314
* changes:
Properly display date and/or time of entries in the new call log.
Add simulator enriched call related to interfaces and stubs.
Diffstat (limited to 'java')
11 files changed, 210 insertions, 52 deletions
diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index 474f6665c..7d277d4b3 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -30,6 +30,7 @@ import com.android.dialer.phonenumbergeoutil.impl.PhoneNumberGeoUtilModule; import com.android.dialer.precall.impl.PreCallModule; import com.android.dialer.preferredsim.suggestion.stub.StubSimSuggestionModule; import com.android.dialer.simulator.impl.SimulatorModule; +import com.android.dialer.simulator.stub.StubSimulatorEnrichedCallModule; import com.android.dialer.spam.StubSpamModule; import com.android.dialer.storage.StorageModule; import com.android.dialer.strictmode.impl.SystemStrictModeModule; @@ -53,6 +54,7 @@ import javax.inject.Singleton; PreCallModule.class, SharedPrefConfigProviderModule.class, SimulatorModule.class, + StubSimulatorEnrichedCallModule.class, StorageModule.class, StubCallLocationModule.class, StubDuoModule.class, diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index 12038b7fb..ff1b09db7 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -30,6 +30,7 @@ import com.android.dialer.phonenumbergeoutil.impl.PhoneNumberGeoUtilModule; import com.android.dialer.precall.impl.PreCallModule; import com.android.dialer.preferredsim.suggestion.stub.StubSimSuggestionModule; import com.android.dialer.simulator.impl.SimulatorModule; +import com.android.dialer.simulator.stub.StubSimulatorEnrichedCallModule; import com.android.dialer.spam.StubSpamModule; import com.android.dialer.storage.StorageModule; import com.android.dialer.strictmode.impl.SystemStrictModeModule; @@ -59,6 +60,7 @@ import javax.inject.Singleton; SharedPrefConfigProviderModule.class, SimulatorModule.class, StorageModule.class, + StubSimulatorEnrichedCallModule.class, StubDuoModule.class, StubEnrichedCallModule.class, StubFeedbackModule.class, diff --git a/java/com/android/dialer/calllogutils/CallLogDates.java b/java/com/android/dialer/calllogutils/CallLogDates.java index 84e52df14..bdf621518 100644 --- a/java/com/android/dialer/calllogutils/CallLogDates.java +++ b/java/com/android/dialer/calllogutils/CallLogDates.java @@ -35,29 +35,52 @@ public final class CallLogDates { * <p>Rules: * * <pre> - * if < 1 minute ago: "Now"; - * else if today: "12:15 PM" - * else if < 3 days ago: "Wednesday"; - * else: "Jan 15" + * if < 1 minute ago: "Just now"; + * else if < 1 hour ago: time relative to now (e.g., "8 min. ago"); + * else if today: time (e.g., "12:15 PM"); + * else if < 7 days: abbreviated day of week (e.g., "Wed"); + * else if < 1 year: date with abbreviated month, day, but no year (e.g., "Jan 15"); + * else: date with abbreviated month, day, and year (e.g., "Jan 15, 2018"). * </pre> */ public static CharSequence newCallLogTimestampLabel( Context context, long nowMillis, long timestampMillis) { + // For calls logged less than 1 minute ago, display "Just now". if (nowMillis - timestampMillis < TimeUnit.MINUTES.toMillis(1)) { - return context.getString(R.string.now); + return context.getString(R.string.just_now); } - if (isSameDay(nowMillis, timestampMillis)) { - return DateUtils.formatDateTime( - context, timestampMillis, DateUtils.FORMAT_SHOW_TIME); // e.g. 12:15 PM + + // For calls logged less than 1 hour ago, display time relative to now (e.g., "8 min. ago"). + if (nowMillis - timestampMillis < TimeUnit.HOURS.toMillis(1)) { + return DateUtils.getRelativeTimeSpanString( + timestampMillis, nowMillis, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE); + } + + int dayDifference = getDayDifference(nowMillis, timestampMillis); + + // For calls logged today, display time (e.g., "12:15 PM"). + if (dayDifference == 0) { + return DateUtils.formatDateTime(context, timestampMillis, DateUtils.FORMAT_SHOW_TIME); } - if (getDayDifference(nowMillis, timestampMillis) < 3) { - return formatDayOfWeek(context, timestampMillis); // e.g. "Wednesday" + + // For calls logged within a week, display the abbreviated day of week (e.g., "Wed"). + if (dayDifference < 7) { + return formatDayOfWeek(context, timestampMillis); + } + + // For calls logged within a year, display abbreviated month, day, but no year (e.g., "Jan 15"). + if (isWithinOneYear(nowMillis, timestampMillis)) { + return formatAbbreviatedDate(context, timestampMillis, /* showYear = */ false); } - return formatAbbreviatedMonthAndDay(context, timestampMillis); // e.g. "Jan 15" + + // For calls logged no less than one year ago, display abbreviated month, day, and year + // (e.g., "Jan 15, 2018"). + return formatAbbreviatedDate(context, timestampMillis, /* showYear = */ true); } /** - * Formats the provided date into a value suitable for display in the current locale. + * Formats the provided timestamp (in milliseconds) into date and time suitable for display in the + * current locale. * * <p>For example, returns a string like "Wednesday, May 25, 2016, 8:02PM" or "Chorshanba, 2016 * may 25,20:02". @@ -65,11 +88,11 @@ public final class CallLogDates { * <p>For pre-N devices, the returned value may not start with a capital if the local convention * is to not capitalize day names. On N+ devices, the returned value is always capitalized. */ - public static CharSequence formatDate(Context context, long callDateMillis) { + public static CharSequence formatDate(Context context, long timestamp) { return toTitleCase( DateUtils.formatDateTime( context, - callDateMillis, + timestamp, DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY @@ -77,30 +100,36 @@ public final class CallLogDates { } /** - * Formats the provided date into the day of week. + * Formats the provided timestamp (in milliseconds) into abbreviated day of week. * - * <p>For example, returns a string like "Wednesday" or "Chorshanba". + * <p>For example, returns a string like "Wed" or "Chor". * * <p>For pre-N devices, the returned value may not start with a capital if the local convention * is to not capitalize day names. On N+ devices, the returned value is always capitalized. */ - private static CharSequence formatDayOfWeek(Context context, long callDateMillis) { + private static CharSequence formatDayOfWeek(Context context, long timestamp) { return toTitleCase( - DateUtils.formatDateTime(context, callDateMillis, DateUtils.FORMAT_SHOW_WEEKDAY)); + DateUtils.formatDateTime( + context, timestamp, DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY)); } /** - * Formats the provided date into the month abbreviation and day. + * Formats the provided timestamp (in milliseconds) into the month abbreviation, day, and + * optionally, year. * - * <p>For example, returns a string like "Jan 15". + * <p>For example, returns a string like "Jan 15" or "Jan 15, 2018". * * <p>For pre-N devices, the returned value may not start with a capital if the local convention * is to not capitalize day names. On N+ devices, the returned value is always capitalized. */ - private static CharSequence formatAbbreviatedMonthAndDay(Context context, long callDateMillis) { - return toTitleCase( - DateUtils.formatDateTime( - context, callDateMillis, DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_NO_YEAR)); + private static CharSequence formatAbbreviatedDate( + Context context, long timestamp, boolean showYear) { + int flags = DateUtils.FORMAT_ABBREV_MONTH; + if (!showYear) { + flags |= DateUtils.FORMAT_NO_YEAR; + } + + return toTitleCase(DateUtils.formatDateTime(context, timestamp, flags)); } private static CharSequence toTitleCase(CharSequence value) { @@ -146,7 +175,7 @@ public final class CallLogDates { * </ul> */ public static int getDayDifference(long firstTimestamp, long secondTimestamp) { - // Ensure secondMillis is no less than firstMillis + // Ensure secondTimestamp is no less than firstTimestamp if (secondTimestamp < firstTimestamp) { long t = firstTimestamp; firstTimestamp = secondTimestamp; @@ -178,16 +207,36 @@ public final class CallLogDates { return dayDifference; } - /** Returns true if the provided timestamps are from the same day in the default time zone. */ - public static boolean isSameDay(long firstMillis, long secondMillis) { - Calendar first = Calendar.getInstance(); - first.setTimeInMillis(firstMillis); + /** + * Returns true if the two timestamps are within one year. It is the caller's responsibility to + * ensure both timestamps are in milliseconds. Failure to do so will result in undefined behavior. + * + * <p>Note that the difference is based on 365/366-day periods. + * + * <p>Examples: + * + * <ul> + * <li>01/01/2018 00:00 and 12/31/2018 23:59 is within one year. + * <li>12/31/2017 23:59 and 12/31/2018 23:59 is not within one year. + * <li>12/31/2017 23:59 and 01/01/2018 00:00 is within one year. + * </ul> + */ + private static boolean isWithinOneYear(long firstTimestamp, long secondTimestamp) { + // Ensure secondTimestamp is no less than firstTimestamp + if (secondTimestamp < firstTimestamp) { + long t = firstTimestamp; + firstTimestamp = secondTimestamp; + secondTimestamp = t; + } + + // Use secondTimestamp as reference + Calendar reference = Calendar.getInstance(); + reference.setTimeInMillis(secondTimestamp); + reference.add(Calendar.YEAR, -1); - Calendar second = Calendar.getInstance(); - second.setTimeInMillis(secondMillis); + Calendar other = Calendar.getInstance(); + other.setTimeInMillis(firstTimestamp); - return first.get(Calendar.YEAR) == second.get(Calendar.YEAR) - && first.get(Calendar.MONTH) == second.get(Calendar.MONTH) - && first.get(Calendar.DAY_OF_MONTH) == second.get(Calendar.DAY_OF_MONTH); + return reference.before(other); } } diff --git a/java/com/android/dialer/calllogutils/CallLogEntryText.java b/java/com/android/dialer/calllogutils/CallLogEntryText.java index 1df44583f..25fe86452 100644 --- a/java/com/android/dialer/calllogutils/CallLogEntryText.java +++ b/java/com/android/dialer/calllogutils/CallLogEntryText.java @@ -49,22 +49,25 @@ public final class CallLogEntryText { return primaryText.toString(); } - /** The secondary text to show in the main call log entry list. */ + /** + * The secondary text to show in the main call log entry list. + * + * <p>Rules: (Duo video, )?$Label|$Location • Date + * + * <p>Examples: + * + * <ul> + * <li>Duo Video, Mobile • Now + * <li>Duo Video • 10 min. ago + * <li>Mobile • 11:45 PM + * <li>Mobile • Sun + * <li>Brooklyn, NJ • Jan 15 + * </ul> + * + * <p>See {@link CallLogDates#newCallLogTimestampLabel(Context, long, long)} for date rules. + */ public static CharSequence buildSecondaryTextForEntries( Context context, Clock clock, CoalescedRow row) { - /* - * Rules: (Duo video, )?$Label|$Location • Date - * - * Examples: - * Duo Video, Mobile • Now - * Duo Video • 11:45pm - * Mobile • 11:45pm - * Mobile • Sunday - * Brooklyn, NJ • Jan 15 - * - * Date rules: - * if < 1 minute ago: "Now"; else if today: HH:MM(am|pm); else if < 3 days: day; else: MON D - */ StringBuilder secondaryText = secondaryTextPrefix(context, row); if (secondaryText.length() > 0) { diff --git a/java/com/android/dialer/calllogutils/res/values/strings.xml b/java/com/android/dialer/calllogutils/res/values/strings.xml index b8ba5b1f3..8784bf8c9 100644 --- a/java/com/android/dialer/calllogutils/res/values/strings.xml +++ b/java/com/android/dialer/calllogutils/res/values/strings.xml @@ -129,7 +129,7 @@ <string name="voicemail_string">Voicemail</string> <!-- String to be displayed to indicate in the call log that a call just now occurred. --> - <string name="now">Now</string> + <string name="just_now">Just now</string> <!-- Text to show in call log for a video call. [CHAR LIMIT=16] --> <string name="new_call_log_video">Video</string> diff --git a/java/com/android/dialer/simulator/SimulatorComponent.java b/java/com/android/dialer/simulator/SimulatorComponent.java index dee188281..6fa3f0cb1 100644 --- a/java/com/android/dialer/simulator/SimulatorComponent.java +++ b/java/com/android/dialer/simulator/SimulatorComponent.java @@ -26,6 +26,8 @@ public abstract class SimulatorComponent { public abstract Simulator getSimulator(); + public abstract SimulatorEnrichedCall getSimulatorEnrichedCall(); + public abstract SimulatorConnectionsBank getSimulatorConnectionsBank(); public static SimulatorComponent get(Context context) { diff --git a/java/com/android/dialer/simulator/SimulatorEnrichedCall.java b/java/com/android/dialer/simulator/SimulatorEnrichedCall.java new file mode 100644 index 000000000..f6c8a6cd9 --- /dev/null +++ b/java/com/android/dialer/simulator/SimulatorEnrichedCall.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 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.simulator; + +import com.android.dialer.enrichedcall.EnrichedCallManager.StateChangedListener; + +/** Setup enriched calling environment for {@link Simulator}. */ +public interface SimulatorEnrichedCall extends StateChangedListener { + /** Setup a session for an incoming enriched call. */ + long setupIncomingEnrichedCall(String number); + + /** Setup a session for outgoing enriched call. */ + long setupOutgoingEnrichedCall(String number); +} diff --git a/java/com/android/dialer/simulator/impl/SimulatorImpl.java b/java/com/android/dialer/simulator/impl/SimulatorImpl.java index 41c234b0e..be8676392 100644 --- a/java/com/android/dialer/simulator/impl/SimulatorImpl.java +++ b/java/com/android/dialer/simulator/impl/SimulatorImpl.java @@ -25,6 +25,7 @@ import javax.inject.Inject; /** The entry point for the simulator feature. */ final class SimulatorImpl implements Simulator { + @Inject public SimulatorImpl() {} diff --git a/java/com/android/dialer/simulator/stub/SimulatorEnrichedCallStub.java b/java/com/android/dialer/simulator/stub/SimulatorEnrichedCallStub.java new file mode 100644 index 000000000..056722fab --- /dev/null +++ b/java/com/android/dialer/simulator/stub/SimulatorEnrichedCallStub.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 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.simulator.stub; + +import com.android.dialer.simulator.SimulatorEnrichedCall; +import javax.inject.Inject; + +/** Stub implementation of {@link SimulatorEnrichedCall}. */ +public class SimulatorEnrichedCallStub implements SimulatorEnrichedCall { + + @Inject + public SimulatorEnrichedCallStub() {} + + @Override + public long setupIncomingEnrichedCall(String number) { + return -1; + } + + @Override + public long setupOutgoingEnrichedCall(String number) { + return -1; + } + + @Override + public void onEnrichedCallStateChanged() {} +} diff --git a/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java b/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java new file mode 100644 index 000000000..36314e7a9 --- /dev/null +++ b/java/com/android/dialer/simulator/stub/StubSimulatorEnrichedCallModule.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 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.simulator.stub; + +import com.android.dialer.simulator.SimulatorEnrichedCall; +import dagger.Binds; +import dagger.Module; +import javax.inject.Singleton; + +/** Provides a stub instance of SimulatorEnrichedCall. */ +@Module +public abstract class StubSimulatorEnrichedCallModule { + @Binds + @Singleton + public abstract SimulatorEnrichedCall bindsSimulatorEnrichedCall( + SimulatorEnrichedCallStub simulatorEnrichedCall); +} diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java index 86d386050..c9bf6e1a8 100644 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java @@ -104,7 +104,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> private final NewVoicemailMediaPlayer mediaPlayer = new NewVoicemailMediaPlayer(new MediaPlayer()); - /** @param cursor whose projection is {@link VoicemailCursorLoader.VOICEMAIL_COLUMNS} */ + /** @param cursor whose projection is {@link VoicemailCursorLoader#VOICEMAIL_COLUMNS} */ NewVoicemailAdapter(Cursor cursor, Clock clock, FragmentManager fragmentManager) { LogUtil.enterBlock("NewVoicemailAdapter"); this.cursor = cursor; @@ -133,14 +133,14 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> long currentTimeMillis = clock.currentTimeMillis(); if (cursor.moveToNext()) { long firstTimestamp = VoicemailCursorLoader.getTimestamp(cursor); - if (CallLogDates.isSameDay(currentTimeMillis, firstTimestamp)) { + if (CallLogDates.getDayDifference(currentTimeMillis, firstTimestamp) == 0) { this.todayHeaderPosition = 0 + alertOffSet; int adapterPosition = 2 + alertOffSet; // Accounted for the "Alert", "Today" header and first row. while (cursor.moveToNext()) { long timestamp = VoicemailCursorLoader.getTimestamp(cursor); - if (CallLogDates.isSameDay(currentTimeMillis, timestamp)) { + if (CallLogDates.getDayDifference(currentTimeMillis, timestamp) == 0) { adapterPosition++; } else { this.olderHeaderPosition = adapterPosition; |