private Entity setupTestEventEntity(String organizer, String attendee, String title) {
    // Create an Entity for an Event
    ContentValues entityValues = new ContentValues();
    Entity entity = new Entity(entityValues);

    // Set up values for the Event
    String location = "Meeting Location";

    // Fill in times, location, title, and organizer
    entityValues.put(
        "DTSTAMP",
        CalendarUtilities.convertEmailDateTimeToCalendarDateTime("2010-04-05T14:30:51Z"));
    entityValues.put(Events.DTSTART, Utility.parseEmailDateTimeToMillis("2010-04-12T18:30:00Z"));
    entityValues.put(Events.DTEND, Utility.parseEmailDateTimeToMillis("2010-04-12T19:30:00Z"));
    entityValues.put(Events.EVENT_LOCATION, location);
    entityValues.put(Events.TITLE, title);
    entityValues.put(Events.ORGANIZER, organizer);
    entityValues.put(Events._SYNC_DATA, "31415926535");

    // Add the attendee
    ContentValues attendeeValues = new ContentValues();
    attendeeValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
    attendeeValues.put(Attendees.ATTENDEE_EMAIL, attendee);
    entity.addSubValue(Attendees.CONTENT_URI, attendeeValues);

    // Add the organizer
    ContentValues organizerValues = new ContentValues();
    organizerValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
    organizerValues.put(Attendees.ATTENDEE_EMAIL, organizer);
    entity.addSubValue(Attendees.CONTENT_URI, organizerValues);
    return entity;
  }
  public void testBuildMessageTextFromEntityValues() {
    // Set up a test event
    String title = "Event Title";
    Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title);
    ContentValues entityValues = entity.getEntityValues();

    // Save this away; we'll use it a few times below
    Resources resources = mContext.getResources();
    Date date = new Date(entityValues.getAsLong(Events.DTSTART));
    String dateTimeString = DateFormat.getDateTimeInstance().format(date);

    // Get the text for this message
    StringBuilder sb = new StringBuilder();
    CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb);
    String text = sb.toString();
    // We'll just check the when and where
    assertTrue(text.contains(resources.getString(R.string.meeting_when, dateTimeString)));
    String location = entityValues.getAsString(Events.EVENT_LOCATION);
    assertTrue(text.contains(resources.getString(R.string.meeting_where, location)));

    // Make this event recurring
    entity.getEntityValues().put(Events.RRULE, "FREQ=WEEKLY;BYDAY=MO");
    sb = new StringBuilder();
    CalendarUtilities.buildMessageTextFromEntityValues(mContext, entityValues, sb);
    text = sb.toString();
    assertTrue(text.contains(resources.getString(R.string.meeting_recurring, dateTimeString)));
  }
  public void testRestrictedQueryParam() throws Exception {
    final long greyContact = mGrey.createContact(true, GENERIC_NAME);
    final long greyPhone = mGrey.createPhone(greyContact, PHONE_GREY);

    final Uri greyUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, greyContact);
    final Uri redUri =
        greyUri
            .buildUpon()
            .appendQueryParameter(ContactsContract.REQUESTING_PACKAGE_PARAM_KEY, mRed.packageName)
            .build();

    // When calling normally, we have access to protected
    mGrey.ensureCallingPackage();
    EntityIterator iterator = mGrey.resolver.queryEntities(greyUri, null, null, null);
    while (iterator.hasNext()) {
      final Entity entity = iterator.next();
      final long rawContactId = entity.getEntityValues().getAsLong(RawContacts._ID);
      assertTrue(rawContactId == greyContact);
    }

    // When calling on behalf of another package, protected is omitted
    mGrey.ensureCallingPackage();
    iterator = mGrey.resolver.queryEntities(redUri, null, null, null);
    while (iterator.hasNext()) {
      final Entity entity = iterator.next();
      final long rawContactId = entity.getEntityValues().getAsLong(RawContacts._ID);
      assertTrue(rawContactId != greyContact);
    }
  }
 private Entity setupTestExceptionEntity(String organizer, String attendee, String title) {
   Entity entity = setupTestEventEntity(organizer, attendee, title);
   ContentValues entityValues = entity.getEntityValues();
   entityValues.put(Events.ORIGINAL_EVENT, 69);
   // The exception will be on April 26th
   entityValues.put(
       Events.ORIGINAL_INSTANCE_TIME, Utility.parseEmailDateTimeToMillis("2010-04-26T18:30:00Z"));
   return entity;
 }
  /** Build an {@link Entity} with the requested set of phone numbers. */
  protected EntityDelta getEntity(Long existingId, ContentValues... entries) {
    final ContentValues contact = new ContentValues();
    if (existingId != null) {
      contact.put(RawContacts._ID, existingId);
    }
    contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
    contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE);

    final Entity before = new Entity(contact);
    for (ContentValues values : entries) {
      before.addSubValue(Data.CONTENT_URI, values);
    }
    return EntityDelta.fromBefore(before);
  }
  public void testCreateMessageForEntity_Exception_Cancel() throws IOException {
    // Set up the "exception"...
    String title = "Discuss Unit Tests";
    Entity entity = setupTestExceptionEntity(ORGANIZER, ATTENDEE, title);

    ContentValues entityValues = entity.getEntityValues();
    // Mark the Exception as dirty
    entityValues.put(Events._SYNC_DIRTY, 1);
    // And mark it canceled
    entityValues.put(Events.STATUS, Events.STATUS_CANCELED);

    // Create a dummy account for the attendee
    Account account = new Account();
    account.mEmailAddress = ORGANIZER;

    // The uid is required, but can be anything
    String uid = "31415926535";

    // Create the outgoing message
    Message msg =
        CalendarUtilities.createMessageForEntity(
            mContext, entity, Message.FLAG_OUTGOING_MEETING_CANCEL, uid, account);

    // First, we should have a message
    assertNotNull(msg);

    // Now check some of the fields of the message
    assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo);
    String cancel = getContext().getResources().getString(R.string.meeting_canceled, title);
    assertEquals(cancel, msg.mSubject);

    // And make sure we have an attachment
    assertNotNull(msg.mAttachments);
    assertEquals(1, msg.mAttachments.size());
    Attachment att = msg.mAttachments.get(0);
    // And that the attachment has the correct elements
    assertEquals("invite.ics", att.mFileName);
    assertEquals(
        Attachment.FLAG_ICS_ALTERNATIVE_PART, att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART);
    assertEquals("text/calendar; method=CANCEL", att.mMimeType);
    assertNotNull(att.mContentBytes);

    // We'll check the contents of the ics file here
    BlockHash vcalendar = parseIcsContent(att.mContentBytes);
    assertNotNull(vcalendar);

    // We should have a VCALENDAR with a CANCEL method
    assertEquals("VCALENDAR", vcalendar.name);
    assertEquals("CANCEL", vcalendar.get("METHOD"));

    // This is the time zone that should be used
    TimeZone timeZone = TimeZone.getDefault();

    // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT)
    assertEquals(2, vcalendar.blocks.size());

    BlockHash vtimezone = vcalendar.blocks.get(0);
    // It should be a VTIMEZONE for timeZone
    assertEquals("VTIMEZONE", vtimezone.name);
    assertEquals(timeZone.getID(), vtimezone.get("TZID"));

    BlockHash vevent = vcalendar.blocks.get(1);
    // It's a VEVENT with the following fields
    assertEquals("VEVENT", vevent.name);
    assertEquals("Meeting Location", vevent.get("LOCATION"));
    assertEquals("0", vevent.get("SEQUENCE"));
    assertEquals("Discuss Unit Tests", vevent.get("SUMMARY"));
    assertEquals(uid, vevent.get("UID"));
    assertEquals("MAILTO:" + ATTENDEE, vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT"));
    long originalTime = entityValues.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
    assertNotSame(0, originalTime);
    // For an exception, RECURRENCE-ID is critical
    assertEquals(
        CalendarUtilities.millisToEasDateTime(originalTime, timeZone, true /*withTime*/),
        vevent.get("RECURRENCE-ID" + ";TZID=" + timeZone.getID()));
  }
  public void testCreateMessageForEntity_Recurring() throws IOException {
    // Set up the "event"
    String title = "Discuss Unit Tests";
    Entity entity = setupTestEventEntity(ORGANIZER, ATTENDEE, title);
    // Set up a RRULE for this event
    entity.getEntityValues().put(Events.RRULE, "FREQ=DAILY");

    // Create a dummy account for the attendee
    Account account = new Account();
    account.mEmailAddress = ORGANIZER;

    // The uid is required, but can be anything
    String uid = "31415926535";

    // Create the outgoing message
    Message msg =
        CalendarUtilities.createMessageForEntity(
            mContext, entity, Message.FLAG_OUTGOING_MEETING_INVITE, uid, account);

    // First, we should have a message
    assertNotNull(msg);

    // Now check some of the fields of the message
    assertEquals(Address.pack(new Address[] {new Address(ATTENDEE)}), msg.mTo);
    assertEquals(title, msg.mSubject);

    // And make sure we have an attachment
    assertNotNull(msg.mAttachments);
    assertEquals(1, msg.mAttachments.size());
    Attachment att = msg.mAttachments.get(0);
    // And that the attachment has the correct elements
    assertEquals("invite.ics", att.mFileName);
    assertEquals(
        Attachment.FLAG_ICS_ALTERNATIVE_PART, att.mFlags & Attachment.FLAG_ICS_ALTERNATIVE_PART);
    assertEquals("text/calendar; method=REQUEST", att.mMimeType);
    assertNotNull(att.mContentBytes);
    assertEquals(att.mSize, att.mContentBytes.length);

    // We'll check the contents of the ics file here
    BlockHash vcalendar = parseIcsContent(att.mContentBytes);
    assertNotNull(vcalendar);

    // We should have a VCALENDAR with a REQUEST method
    assertEquals("VCALENDAR", vcalendar.name);
    assertEquals("REQUEST", vcalendar.get("METHOD"));

    // We should have two blocks under VCALENDAR (VTIMEZONE and VEVENT)
    assertEquals(2, vcalendar.blocks.size());

    // This is the time zone that should be used
    TimeZone timeZone = TimeZone.getDefault();

    BlockHash vtimezone = vcalendar.blocks.get(0);
    // It should be a VTIMEZONE for timeZone
    assertEquals("VTIMEZONE", vtimezone.name);
    assertEquals(timeZone.getID(), vtimezone.get("TZID"));

    BlockHash vevent = vcalendar.blocks.get(1);
    // It's a VEVENT with the following fields
    assertEquals("VEVENT", vevent.name);
    assertEquals("Meeting Location", vevent.get("LOCATION"));
    assertEquals("0", vevent.get("SEQUENCE"));
    assertEquals("Discuss Unit Tests", vevent.get("SUMMARY"));
    assertEquals(uid, vevent.get("UID"));
    assertEquals(
        "MAILTO:" + ATTENDEE,
        vevent.get("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE"));

    // We should have DTSTART/DTEND with time zone
    assertNotNull(vevent.get("DTSTART;TZID=" + timeZone.getID()));
    assertNotNull(vevent.get("DTEND;TZID=" + timeZone.getID()));
    assertNull(vevent.get("DTSTART"));
    assertNull(vevent.get("DTEND"));
    assertNull(vevent.get("DTSTART;VALUE=DATE"));
    assertNull(vevent.get("DTEND;VALUE=DATE"));
    // This shouldn't exist for this event
    assertNull(vevent.get("X-MICROSOFT-CDO-ALLDAYEVENT"));
  }