summaryrefslogtreecommitdiff
path: root/InCallUI/src
diff options
context:
space:
mode:
authorNancy Chen <nancychen@google.com>2015-10-20 17:12:01 -0700
committerNancy Chen <nancychen@google.com>2015-10-21 18:03:37 -0700
commitd2fda4ab69205fc672c02141f9b62c1958f73ace (patch)
treeff3cdd32f5bb937cb04f69fa12f146594ea04d31 /InCallUI/src
parent3867a0ac286d0c9cc457b81e9db5d36019e786e4 (diff)
Add hours of operation info to incall business context.
Display hours of operation information if it is available. If hours of operation are available, also determine whether it is currently open or closed. Display in the InCallUI when making a business call. Also add tests to make sure that the business context object is constructed correctly. Bug: 23351559 Change-Id: Ic2846e54e15ade37ccf0b916651cc3388da3cc23
Diffstat (limited to 'InCallUI/src')
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java7
-rw-r--r--InCallUI/src/com/android/incallui/ContactInfoCache.java15
-rw-r--r--InCallUI/src/com/android/incallui/ContactUtils.java6
-rw-r--r--InCallUI/src/com/android/incallui/InCallContactInteractions.java127
4 files changed, 129 insertions, 26 deletions
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index aa022f448..e7d6f0c3e 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -595,8 +595,8 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
private void updateContactInteractions() {
if (mPrimary != null && mPrimaryContactInfo != null
- && mPrimaryContactInfo.locationAddress != null) {
-
+ && (mPrimaryContactInfo.locationAddress != null
+ || mPrimaryContactInfo.openingHours != null)) {
// TODO: This is hardcoded to "isBusiness" because functionality to differentiate
// between business and personal has not yet been added.
if (setInCallContactInteractionsType(true /* isBusiness */)) {
@@ -606,7 +606,8 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
mInCallContactInteractions.setBusinessInfo(
mPrimaryContactInfo.locationAddress,
- mDistanceHelper.calculateDistance(mPrimaryContactInfo.locationAddress));
+ mDistanceHelper.calculateDistance(mPrimaryContactInfo.locationAddress),
+ mPrimaryContactInfo.openingHours);
getUi().setContactContextContent(mInCallContactInteractions.getListAdapter());
getUi().showContactContext(mPrimary.getState() != State.INCOMING);
}
diff --git a/InCallUI/src/com/android/incallui/ContactInfoCache.java b/InCallUI/src/com/android/incallui/ContactInfoCache.java
index 0e6a3d4e0..e3457d5cb 100644
--- a/InCallUI/src/com/android/incallui/ContactInfoCache.java
+++ b/InCallUI/src/com/android/incallui/ContactInfoCache.java
@@ -30,6 +30,7 @@ import android.provider.ContactsContract.DisplayNameSources;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.contacts.common.util.PhoneNumberHelper;
import com.android.dialer.calllog.ContactInfo;
@@ -299,10 +300,11 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
entry.photo = mContext.getResources().getDrawable(R.drawable.img_business);
}
- String address = null;
+ boolean hasContactInteractions = false;
if (mContactUtils != null) {
- // This method will callback "onAddressDetailsFound".
- address = mContactUtils.getAddressFromLookupKey(info.getLookupKey(), this);
+ // This method will callback "onContactInteractionsFound".
+ hasContactInteractions = mContactUtils.retrieveContactInteractionsFromLookupKey(
+ info.getLookupKey(), this);
}
// Add the contact info to the cache.
@@ -310,7 +312,7 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
sendInfoNotifications(mCallId, entry);
// If there is no image then we should not expect another callback.
- if (info.getImageUrl() == null && address == null) {
+ if (info.getImageUrl() == null && !hasContactInteractions) {
// We're done, so clear callbacks
clearCallbacks(mCallId);
}
@@ -322,9 +324,10 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
}
@Override
- public void onAddressDetailsFound(Address address) {
+ public void onContactInteractionsFound(Address address, Pair<String, String> openingHours) {
final ContactCacheEntry entry = mInfoMap.get(mCallId);
entry.locationAddress = address;
+ entry.openingHours = openingHours;
sendContactInteractionsNotifications(mCallId, entry);
clearCallbacks(mCallId);
}
@@ -614,6 +617,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 int contactLookupResult = LogState.LOOKUP_NOT_FOUND;
@Override
@@ -628,6 +632,7 @@ public class ContactInfoCache implements ContactsAsyncHelper.OnImageLoadComplete
.add("contactUri", contactUri)
.add("displayPhotoUri", displayPhotoUri)
.add("locationAddress", locationAddress)
+ .add("openingHours", openingHours)
.add("contactLookupResult", contactLookupResult)
.toString();
}
diff --git a/InCallUI/src/com/android/incallui/ContactUtils.java b/InCallUI/src/com/android/incallui/ContactUtils.java
index eac748494..dfacade8a 100644
--- a/InCallUI/src/com/android/incallui/ContactUtils.java
+++ b/InCallUI/src/com/android/incallui/ContactUtils.java
@@ -17,6 +17,7 @@ package com.android.incallui;
import android.content.Context;
import android.location.Address;
+import android.util.Pair;
import com.android.incalluibind.ObjectFactory;
@@ -35,8 +36,9 @@ public abstract class ContactUtils {
}
public interface Listener {
- public void onAddressDetailsFound(Address address);
+ public void onContactInteractionsFound(Address address, Pair<String, String> openingHours);
}
- public abstract String getAddressFromLookupKey(String lookupKey, Listener listener);
+ public abstract boolean retrieveContactInteractionsFromLookupKey(String lookupKey,
+ Listener listener);
}
diff --git a/InCallUI/src/com/android/incallui/InCallContactInteractions.java b/InCallUI/src/com/android/incallui/InCallContactInteractions.java
index 04caecc13..6d1c9fc8f 100644
--- a/InCallUI/src/com/android/incallui/InCallContactInteractions.java
+++ b/InCallUI/src/com/android/incallui/InCallContactInteractions.java
@@ -16,9 +16,13 @@
package com.android.incallui;
+import com.google.common.annotations.VisibleForTesting;
+
import android.content.Context;
import android.location.Address;
import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -29,7 +33,11 @@ import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
import java.util.Locale;
@@ -41,6 +49,7 @@ 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;
@@ -77,11 +86,6 @@ public class InCallContactInteractions {
return false;
}
- public void setBusinessInfo(Address address, float distance) {
- mListAdapter.clear();
- mListAdapter.addAll(constructBusinessContextInfo(address, distance));
- }
-
public View getBusinessListHeaderView() {
if (mBusinessHeaderView == null) {
mBusinessHeaderView = mInflater.inflate(
@@ -90,30 +94,121 @@ public class InCallContactInteractions {
return mBusinessHeaderView;
}
- private List<ContactContextInfo> constructBusinessContextInfo(Address address, float distance) {
+ public void setBusinessInfo(Address address, float distance,
+ Pair<String, String> openingHours) {
+ mListAdapter.clear();
List<ContactContextInfo> info = new ArrayList<ContactContextInfo>();
- //TODO: hours of operation information
+ // Hours of operation
+ if (openingHours != null) {
+ BusinessContextInfo hoursInfo = constructHoursInfo(openingHours);
+ if (hoursInfo != null) {
+ info.add(hoursInfo);
+ }
+ }
// Location information
- BusinessContextInfo distanceInfo = new BusinessContextInfo();
- distanceInfo.iconId = R.drawable.ic_location_on_white_24dp;
+ if (address != null) {
+ BusinessContextInfo locationInfo = constructLocationInfo(address, distance);
+ info.add(locationInfo);
+ }
+
+ mListAdapter.addAll(info);
+ }
+
+ /**
+ * Construct a BusinessContextInfo object containing hours of operation information.
+ * The format is:
+ * [Open now/Closed now]
+ * [Hours]
+ *
+ * @param openingHours
+ * @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) {
+ return constructHoursInfoByTime(Calendar.getInstance(), openingHours);
+ }
+
+ /**
+ * Pass in arbitrary current calendar time.
+ */
+ @VisibleForTesting
+ BusinessContextInfo constructHoursInfoByTime(
+ Calendar currentTime, Pair<String, String> openingHours) {
+ BusinessContextInfo hoursInfo = new BusinessContextInfo();
+ hoursInfo.iconId = R.drawable.ic_schedule_white_24dp;
+
+ Calendar openTime = getCalendarFromTime(currentTime, openingHours.first);
+ Calendar closeTime = getCalendarFromTime(currentTime, openingHours.second);
+
+ if (openTime == null || closeTime == null) {
+ return null;
+ }
+
+ if (currentTime.after(openTime) && currentTime.before(closeTime)) {
+ hoursInfo.heading = mContext.getString(R.string.open_now);
+ } else {
+ hoursInfo.heading = mContext.getString(R.string.closed_now);
+ }
+
+ hoursInfo.detail = mContext.getString(
+ R.string.opening_hours,
+ DateFormat.getTimeFormat(mContext).format(openTime.getTime()),
+ DateFormat.getTimeFormat(mContext).format(closeTime.getTime()));
+ return hoursInfo;
+ }
+
+ /**
+ * Construct a BusinessContextInfo object with the location information of the business.
+ * The format is:
+ * [Straight line distance in miles or kilometers]
+ * [Address without state/country/etc.]
+ *
+ * @param address An Address object containing address details of the business
+ * @param distance The distance to the location in meters
+ * @return A BusinessContextInfo object with the location icon, the heading as the distance to
+ * the business and the details containing the address.
+ */
+ @VisibleForTesting
+ BusinessContextInfo constructLocationInfo(Address address, float distance) {
+ if (address == null) {
+ return null;
+ }
+
+ BusinessContextInfo locationInfo = new BusinessContextInfo();
+ locationInfo.iconId = R.drawable.ic_location_on_white_24dp;
if (distance != DistanceHelper.DISTANCE_NOT_FOUND) {
//TODO: add a setting to allow the user to select "KM" or "MI" as their distance units.
if (Locale.US.equals(Locale.getDefault())) {
- distanceInfo.heading = mContext.getString(R.string.distance_imperial_away,
+ locationInfo.heading = mContext.getString(R.string.distance_imperial_away,
distance * DistanceHelper.MILES_PER_METER);
} else {
- distanceInfo.heading = mContext.getString(R.string.distance_metric_away,
+ locationInfo.heading = mContext.getString(R.string.distance_metric_away,
distance * DistanceHelper.KILOMETERS_PER_METER);
}
}
- if (address != null) {
- distanceInfo.detail = address.getAddressLine(0);
- }
- info.add(distanceInfo);
+ locationInfo.detail = address.getAddressLine(0);
+ return locationInfo;
+ }
- return info;
+ /**
+ * Get a calendar object set to the current calendar date and the time set to the "hhmm" string
+ * passed in.
+ */
+ private Calendar getCalendarFromTime(Calendar currentTime, String time) {
+ try {
+ Calendar newCalendar = Calendar.getInstance();
+ newCalendar.setTime(new SimpleDateFormat("hhmm").parse(time));
+ newCalendar.set(
+ currentTime.get(Calendar.YEAR),
+ currentTime.get(Calendar.MONTH),
+ currentTime.get(Calendar.DATE));
+ return newCalendar;
+ } catch (ParseException e) {
+ Log.w(TAG, "Could not parse time string" + time);
+ }
+ return null;
}
/**