diff options
author | Nancy Chen <nancychen@google.com> | 2015-11-11 01:14:47 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2015-11-11 01:14:47 +0000 |
commit | f43c5792be6a9df8201bb6fb545988a1bda529ef (patch) | |
tree | 8c57ec5ed3a277123e900e9d1d2fa90e22be5992 | |
parent | 5e5835d7427f4a0f4381d7f7cda58d25265325f4 (diff) | |
parent | 32f7b406d7ba204649c9c73b3466d725ba9e91f5 (diff) |
Merge "Account for multiple open times for business contacts." into ub-contactsdialer-a-dev am: c3e0717a4b
am: 839ce5427c
* commit '839ce5427c6440d41925b0833db9497f5833c1c2':
Account for multiple open times for business contacts.
5 files changed, 189 insertions, 109 deletions
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml index 2f8ef8a41..54d68c9d2 100644 --- a/InCallUI/res/values/strings.xml +++ b/InCallUI/res/values/strings.xml @@ -479,8 +479,14 @@ <string name="distance_metric_away"><xliff:g id="distance">%.1f</xliff:g> km away</string> <!-- A shortened way to display a business address. Formatted [street address], [city/locality]. --> <string name="display_address"><xliff:g id="street_address">%1$s</xliff:g>, <xliff:g id="locality">%2$s</xliff:g></string> - <!-- Used to indicate the opening hours for a location as a time span. e.g. "11 am - 9 pm" [CHAR LIMIT=NONE] --> - <string name="opening_hours"><xliff:g id="open_time">%1$s</xliff:g> - <xliff:g id="close_time">%2$s</xliff:g></string> + <!-- Used to indicate hours of operation for a location as a time span. e.g. "11 am - 9 pm" [CHAR LIMIT=NONE] --> + <string name="open_time_span"><xliff:g id="open_time">%1$s</xliff:g> - <xliff:g id="close_time">%2$s</xliff:g></string> + <!-- Used to indicate a series of opening hours for a location. + This first argument may be one or more time spans. e.g. "11 am - 9 pm, 9 pm - 11 pm" + The second argument is an additional time span. e.g. "11 pm - 1 am" + The string is used to build a list of opening hours. + [CHAR LIMIT=NONE] --> + <string name="opening_hours"><xliff:g id="earlier_times">%1$s</xliff:g>, <xliff:g id="later_time">%2$s</xliff:g></string> <!-- Displayed when a place is open. --> <string name="open_now">Open now</string> <!-- Displayed when a place is closed. --> diff --git a/InCallUI/src/com/android/incallui/ContactInfoCache.java b/InCallUI/src/com/android/incallui/ContactInfoCache.java index 90284d53a..54152eb60 100644 --- a/InCallUI/src/com/android/incallui/ContactInfoCache.java +++ b/InCallUI/src/com/android/incallui/ContactInfoCache.java @@ -49,7 +49,9 @@ import com.android.incalluibind.ObjectFactory; import org.json.JSONException; import org.json.JSONObject; +import java.util.Calendar; import java.util.HashMap; +import java.util.List; import java.util.Set; /** @@ -324,7 +326,8 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete } @Override - public void onContactInteractionsFound(Address address, Pair<String, String> openingHours) { + public void onContactInteractionsFound(Address address, + List<Pair<Calendar, Calendar>> openingHours) { final ContactCacheEntry entry = mInfoMap.get(mCallId); entry.locationAddress = address; entry.openingHours = openingHours; @@ -629,7 +632,7 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete public Uri lookupUri; // Sent to NotificationMananger public String lookupKey; public Address locationAddress; - public Pair<String, String> openingHours; + public List<Pair<Calendar, Calendar>> openingHours; public int contactLookupResult = LogState.LOOKUP_NOT_FOUND; @Override diff --git a/InCallUI/src/com/android/incallui/ContactUtils.java b/InCallUI/src/com/android/incallui/ContactUtils.java index dfacade8a..0750af731 100644 --- a/InCallUI/src/com/android/incallui/ContactUtils.java +++ b/InCallUI/src/com/android/incallui/ContactUtils.java @@ -21,6 +21,9 @@ import android.util.Pair; import com.android.incalluibind.ObjectFactory; +import java.util.Calendar; +import java.util.List; + /** * Utility functions to help manipulate contact data. */ @@ -36,7 +39,8 @@ public abstract class ContactUtils { } public interface Listener { - public void onContactInteractionsFound(Address address, Pair<String, String> openingHours); + public void onContactInteractionsFound(Address address, + List<Pair<Calendar, Calendar>> openingHours); } public abstract boolean retrieveContactInteractionsFromLookupKey(String lookupKey, diff --git a/InCallUI/src/com/android/incallui/InCallContactInteractions.java b/InCallUI/src/com/android/incallui/InCallContactInteractions.java index 21660cbce..275243e4d 100644 --- a/InCallUI/src/com/android/incallui/InCallContactInteractions.java +++ b/InCallUI/src/com/android/incallui/InCallContactInteractions.java @@ -49,7 +49,6 @@ import java.util.Locale; * is a business contact or not and logic for the manipulation of data for the call context. */ public class InCallContactInteractions { - private static final String TAG = InCallContactInteractions.class.getSimpleName(); private Context mContext; private InCallContactInteractionsListAdapter mListAdapter; private boolean mIsBusiness; @@ -95,7 +94,7 @@ public class InCallContactInteractions { } public void setBusinessInfo(Address address, float distance, - Pair<String, String> openingHours) { + List<Pair<Calendar, Calendar>> openingHours) { mListAdapter.clear(); List<ContactContextInfo> info = new ArrayList<ContactContextInfo>(); @@ -126,7 +125,7 @@ public class InCallContactInteractions { * @return BusinessContextInfo object with the schedule icon, the heading set to whether the * business is open or not and the details set to the hours of operation. */ - private BusinessContextInfo constructHoursInfo(Pair<String, String> openingHours) { + private BusinessContextInfo constructHoursInfo(List<Pair<Calendar, Calendar>> openingHours) { return constructHoursInfo(Calendar.getInstance(), openingHours); } @@ -135,26 +134,38 @@ public class InCallContactInteractions { */ @VisibleForTesting BusinessContextInfo constructHoursInfo(Calendar currentTime, - Pair<String, String> openingHours) { + List<Pair<Calendar, Calendar>> openingHours) { + if (currentTime == null || openingHours == null || openingHours.size() == 0) { + return null; + } + BusinessContextInfo hoursInfo = new BusinessContextInfo(); hoursInfo.iconId = R.drawable.ic_schedule_white_24dp; - // Note: the date of these {@link Date}s are set to January 1, 1970. The object is just - // used as a storage for the time. - Date openingDateTime = getSimpleDateTime(openingHours.first); - Date closingDateTime = getSimpleDateTime(openingHours.second); + boolean isOpen = false; + for (Pair<Calendar, Calendar> hours : openingHours) { + if (hours.first.compareTo(currentTime) <= 0 + && currentTime.compareTo(hours.second) < 0) { + // If the current time is on or after the opening time and strictly before the + // closing time, then this business is open. + isOpen = true; + } - if (openingDateTime == null || closingDateTime == null) { - return null; + String openTimeSpan = mContext.getString(R.string.open_time_span, + DateFormat.getTimeFormat(mContext).format(hours.first.getTime()), + DateFormat.getTimeFormat(mContext).format(hours.second.getTime())); + + if (TextUtils.isEmpty(hoursInfo.detail)) { + hoursInfo.detail = openTimeSpan; + } else { + hoursInfo.detail = mContext.getString(R.string.opening_hours, hoursInfo.detail, + openTimeSpan); + } } - hoursInfo.heading = isOpen(openingDateTime, closingDateTime, currentTime) - ? mContext.getString(R.string.open_now) : mContext.getString(R.string.closed_now); + hoursInfo.heading = isOpen ? mContext.getString(R.string.open_now) + : mContext.getString(R.string.closed_now); - hoursInfo.detail = mContext.getString( - R.string.opening_hours, - DateFormat.getTimeFormat(mContext).format(openingDateTime), - DateFormat.getTimeFormat(mContext).format(closingDateTime)); return hoursInfo; } @@ -204,57 +215,6 @@ public class InCallContactInteractions { } /** - * Get a {@link Date} object corresponding to a particular time. - * - * @param time A string containing a time in the format "hhmm". - * @return A {@link Date} object with the time set to the parsed value of the "time" parameter - * and the date set to January 1, 1970. Or {@code null} if the input string is not able to be - * parsed. - */ - private Date getSimpleDateTime(String time) { - try { - return new SimpleDateFormat("hhmm").parse(time); - } catch (ParseException e) { - Log.w(TAG, "Could not parse time string " + time); - } - return null; - } - - /** - * Check whether the current time falls between the opening time and the closing time. - * - * @param openingTime A {@link Date} object with the time set to the opening time and the date - * set to January 1, 1970. - * @param closingTime A {@link Date} object with the time set to the closing time and the date - * set to January 1, 1970. - * @param currentDateTime A {@link Calendar} object with the current date and time. - * @return {@code true} if the current time falls within the opening and closing time bounds and - * {@code false} otherwise. - */ - private boolean isOpen(Date openingTime, Date closingTime, Calendar currentDateTime) { - Calendar openTimeCalendar = Calendar.getInstance(); - openTimeCalendar.setTime(openingTime); - - Calendar closeTimeCalendar = Calendar.getInstance(); - closeTimeCalendar.setTime(closingTime); - - if (openTimeCalendar.compareTo(closeTimeCalendar) >= 0) { - // If the open time is the same or after the close time, add a day to the close time - // calendar. - closeTimeCalendar.add(Calendar.DATE, 1); - } - - // Since the date doesn't actually matter, it's easier to set the current date to the - // opening date rather than change both the calendars for the open time and the close time. - currentDateTime.set( - openTimeCalendar.get(Calendar.YEAR), - openTimeCalendar.get(Calendar.MONTH), - openTimeCalendar.get(Calendar.DATE)); - - return currentDateTime.after(openTimeCalendar) && currentDateTime.before(closeTimeCalendar); - } - - /** * Get the appropriate title for the context. * @return The "Business info" title for a business contact and the "Recent messages" title for * personal contacts. diff --git a/InCallUI/tests/src/com/android/incallui/InCallContactInteractionsTest.java b/InCallUI/tests/src/com/android/incallui/InCallContactInteractionsTest.java index 50d0aaf6c..0d03848b6 100644 --- a/InCallUI/tests/src/com/android/incallui/InCallContactInteractionsTest.java +++ b/InCallUI/tests/src/com/android/incallui/InCallContactInteractionsTest.java @@ -22,9 +22,18 @@ import android.util.Pair; import com.android.incallui.InCallContactInteractions.BusinessContextInfo; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Locale; +/** + * Tests for InCallContactInteractions class methods for formatting info for display. + * + * NOTE: tests assume system settings are set to 12hr time format and US locale. This means that + * the output of InCallContactInteractions methods are compared against strings in 12hr time format + * and US locale address formatting unless otherwise specified. + */ public class InCallContactInteractionsTest extends AndroidTestCase { private InCallContactInteractions mInCallContactInteractions; private static final float TEST_DISTANCE = (float) 1234.56; @@ -34,64 +43,147 @@ public class InCallContactInteractionsTest extends AndroidTestCase { mInCallContactInteractions = new InCallContactInteractions(mContext, true /* isBusiness */); } - public void testIsOpenNow() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 10); - BusinessContextInfo info = + public void testIsOpenNow_NowMatchesOpenTime() { + assertEquals(mContext.getString(R.string.open_now), mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("0800", "2000")); - assertEquals(mContext.getString(R.string.open_now), info.heading); + getTestCalendarWithHour(8), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(20)))) + .heading); } public void testIsOpenNow_ClosingAfterMidnight() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 10); - BusinessContextInfo info = + assertEquals(mContext.getString(R.string.open_now), mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("0800", "0100")); - assertEquals(mContext.getString(R.string.open_now), info.heading); + getTestCalendarWithHour(10), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHourAndDaysFromToday(1, 1)))) + .heading); } public void testIsOpenNow_Open24Hours() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 10); - BusinessContextInfo info = + assertEquals(mContext.getString(R.string.open_now), + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(10), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHourAndDaysFromToday(8, 1)))) + .heading); + } + + public void testIsOpenNow_AfterMiddayBreak() { + assertEquals(mContext.getString(R.string.open_now), mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("0800", "0800")); - assertEquals(mContext.getString(R.string.open_now), info.heading); + getTestCalendarWithHour(13), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(10)), + Pair.create( + getTestCalendarWithHour(12), + getTestCalendarWithHour(15)))) + .heading); + } + + public void testIsClosedNow_DuringMiddayBreak() { + assertEquals(mContext.getString(R.string.closed_now), + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(11), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(10)), + Pair.create( + getTestCalendarWithHour(12), + getTestCalendarWithHour(15)))) + .heading); } public void testIsClosedNow_BeforeOpen() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 6); - BusinessContextInfo info = + assertEquals(mContext.getString(R.string.closed_now), mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("0800", "2000")); - assertEquals(mContext.getString(R.string.closed_now), info.heading); + getTestCalendarWithHour(6), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(20)))) + .heading); + } + + public void testIsClosedNow_NowMatchesClosedTime() { + assertEquals(mContext.getString(R.string.closed_now), + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(20), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(20)))) + .heading); } public void testIsClosedNow_AfterClosed() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 21); - BusinessContextInfo info = + assertEquals(mContext.getString(R.string.closed_now), mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("0800", "2000")); - assertEquals(mContext.getString(R.string.closed_now), info.heading); + getTestCalendarWithHour(21), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(20)))) + .heading); + } + + public void testOpeningHours_SingleOpenRange() { + assertEquals("8:00 AM - 8:00 PM", + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(21), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(20)))) + .detail); + } + + public void testOpeningHours_TwoOpenRanges() { + assertEquals("8:00 AM - 10:00 AM, 12:00 PM - 3:00 PM", + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(13), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(10)), + Pair.create( + getTestCalendarWithHour(12), + getTestCalendarWithHour(15)))) + .detail); + } + + public void testOpeningHours_MultipleOpenRanges() { + assertEquals("8:00 AM - 10:00 AM, 12:00 PM - 3:00 PM, 5:00 PM - 9:00 PM", + mInCallContactInteractions.constructHoursInfo( + getTestCalendarWithHour(13), + Arrays.asList( + Pair.create( + getTestCalendarWithHour(8), + getTestCalendarWithHour(10)), + Pair.create( + getTestCalendarWithHour(12), + getTestCalendarWithHour(15)), + Pair.create( + getTestCalendarWithHour(17), + getTestCalendarWithHour(21)))) + .detail); } public void testInvalidOpeningHours() { - Calendar currentTimeForTest = Calendar.getInstance(); - currentTimeForTest.set(Calendar.HOUR_OF_DAY, 21); - BusinessContextInfo info = + assertEquals(null, mInCallContactInteractions.constructHoursInfo( - currentTimeForTest, - Pair.create("", "2000")); - assertEquals(null, info); + getTestCalendarWithHour(21), + new ArrayList<Pair<Calendar, Calendar>>())); } public void testLocationInfo_ForUS() { @@ -150,4 +242,19 @@ public class InCallContactInteractionsTest extends AndroidTestCase { address.setLocality("Test locality"); return address; } + + private Calendar getTestCalendarWithHour(int hour) { + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + return calendar; + } + + private Calendar getTestCalendarWithHourAndDaysFromToday(int hour, int daysFromToday) { + Calendar calendar = getTestCalendarWithHour(hour); + calendar.add(Calendar.DATE, daysFromToday); + return calendar; + } } |