public ContactInfo lookupContact(
      String number, int numberPresentation, String countryIso, ContactInfo cachedContactInfo) {
    NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
    ExpirableCache.CachedValue<ContactInfo> cachedInfo =
        mContactInfoCache.getCachedValue(numberCountryIso);
    ContactInfo info = cachedInfo == null ? null : cachedInfo.getValue();
    if (!PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation)
        || new PhoneNumberUtilsWrapper().isVoicemailNumber(number)) {
      // If this is a number that cannot be dialed, there is no point in looking up a contact
      // for it.
      info = ContactInfo.EMPTY;
    } else if (cachedInfo == null) {
      mContactInfoCache.put(numberCountryIso, ContactInfo.EMPTY);
      // Use the cached contact info from the call log.
      info = cachedContactInfo;
      // The db request should happen on a non-UI thread.
      // Request the contact details immediately since they are currently missing.
      enqueueRequest(number, countryIso, cachedContactInfo, true);
      // We will format the phone number when we make the background request.
    } else {
      if (cachedInfo.isExpired()) {
        // The contact info is no longer up to date, we should request it. However, we
        // do not need to request them immediately.
        enqueueRequest(number, countryIso, cachedContactInfo, false);
      } else if (!callLogInfoMatches(cachedContactInfo, info)) {
        // The call log information does not match the one we have, look it up again.
        // We could simply update the call log directly, but that needs to be done in a
        // background thread, so it is easier to simply request a new lookup, which will, as
        // a side-effect, update the call log.
        enqueueRequest(number, countryIso, cachedContactInfo, false);
      }

      if (info == ContactInfo.EMPTY) {
        // Use the cached contact info from the call log.
        info = cachedContactInfo;
      }
    }

    return info;
  }