Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfe1297b authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 26869 into eclair

* changes:
  Add call log support to pim.vcard.VCardComposer
parents 1267b0e1 c3eef96b
Loading
Loading
Loading
Loading
+202 −38
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@ import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.CallLog.Calls;
import android.provider.CallLog;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.text.TextUtils;
import android.util.CharsetUtils;
import android.util.Log;
@@ -213,6 +217,9 @@ public class VCardComposer {
    private static final String VCARD_PROPERTY_X_NICKNAME = "X-NICKNAME";
    // TODO: add properties like X-LATITUDE

    // Property for call log entry
    private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";

    // Properties for DoCoMo vCard.
    private static final String VCARD_PROPERTY_X_CLASS = "X-CLASS";
    private static final String VCARD_PROPERTY_X_REDUCTION = "X-REDUCTION";
@@ -227,6 +234,7 @@ public class VCardComposer {
    private static final String VCARD_DATA_SEPARATOR = ":";
    private static final String VCARD_ITEM_SEPARATOR = ";";
    private static final String VCARD_WS = " ";
    private static final String VCARD_ATTR_EQUAL = "=";

    // Type strings are now in VCardConstants.java.

@@ -238,20 +246,20 @@ public class VCardComposer {
    private static final String SHIFT_JIS = "SHIFT_JIS";

    private final Context mContext;
    private final int mVCardType;
    private final boolean mCareHandlerErrors;
    private final ContentResolver mContentResolver;
    private int mVCardType;
    private boolean mCareHandlerErrors;
    private ContentResolver mContentResolver;

    // Convenient member variables about the restriction of the vCard format.
    // Used for not calling the same methods returning same results.
    private final boolean mIsV30;
    private final boolean mIsJapaneseMobilePhone;
    private final boolean mOnlyOneNoteFieldIsAvailable;
    private final boolean mIsDoCoMo;
    private final boolean mUsesQuotedPrintable;
    private final boolean mUsesAndroidProperty;
    private final boolean mUsesDefactProperty;
    private final boolean mUsesShiftJis;
    private boolean mIsV30;
    private boolean mIsJapaneseMobilePhone;
    private boolean mOnlyOneNoteFieldIsAvailable;
    private boolean mIsDoCoMo;
    private boolean mUsesQuotedPrintable;
    private boolean mUsesAndroidProperty;
    private boolean mUsesDefactProperty;
    private boolean mUsesShiftJis;

    private Cursor mCursor;
    private int mIdColumn;
@@ -276,6 +284,25 @@ public class VCardComposer {
        // Google talk is a special case.
    }

    private boolean mIsCallLogComposer = false;

    private static final String[] CONTACTS_PROJECTION = new String[] {
        Contacts._ID,
    };

    /** The projection to use when querying the call log table */
    private static final String[] CALL_LOG_PROJECTION = new String[] {
            Calls.NUMBER, Calls.DATE, Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
            Calls.CACHED_NUMBER_LABEL
    };
    private static final int NUMBER_COLUMN_INDEX = 0;
    private static final int DATE_COLUMN_INDEX = 1;
    private static final int CALL_TYPE_COLUMN_INDEX = 2;
    private static final int CALLER_NAME_COLUMN_INDEX = 3;
    private static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 4;
    private static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 5;

    private static final String FLAG_TIMEZONE_UTC = "Z";

    public VCardComposer(Context context) {
        this(context, VCardConfig.VCARD_TYPE_DEFAULT, true);
@@ -287,10 +314,15 @@ public class VCardComposer {
                careHandlerErrors);
    }

    public VCardComposer(Context context, int vcardType, boolean careHandlerErrors) {
    /**
     * Construct for supporting call log entry vCard composing
     */
    public VCardComposer(Context context, int vcardType, boolean careHandlerErrors,
            boolean isCallLogComposer) {
        mContext = context;
        mVCardType = vcardType;
        mCareHandlerErrors = careHandlerErrors;
        mIsCallLogComposer = isCallLogComposer;
        mContentResolver = context.getContentResolver();

        mIsV30 = VCardConfig.isV30(vcardType);
@@ -320,6 +352,38 @@ public class VCardComposer {
        }
    }

    public VCardComposer(Context context, int vcardType, boolean careHandlerErrors) {
        this(context, vcardType, careHandlerErrors, false);
    }

    /**
     * This static function is to compose vCard for phone own number
     */
    public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
            String phoneNumber, boolean vcardVer21) {
        final StringBuilder builder = new StringBuilder();
        appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);
        if (!vcardVer21) {
            appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30);
        } else {
            appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21);
        }

        boolean needCharset = false;
        if (!(VCardUtils.containsOnlyAscii(phoneName))) {
            needCharset = true;
        }
        appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, phoneName, needCharset, false);
        appendVCardLine(builder, VCARD_PROPERTY_NAME, phoneName, needCharset, false);

        String label = Integer.toString(phonetype);
        appendVCardTelephoneLine(builder, phonetype, label, phoneNumber);

        appendVCardLine(builder, VCARD_PROPERTY_END, VCARD_DATA_VCARD);

        return builder.toString();
    }

    /**
     * Must call before {{@link #init()}.
     */
@@ -357,11 +421,15 @@ public class VCardComposer {
            }
        }

        final String[] projection = new String[] {Contacts._ID,};

        if (mIsCallLogComposer) {
            mCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, CALL_LOG_PROJECTION,
                    selection, selectionArgs, null);
        } else {
            // TODO: thorow an appropriate exception!
        mCursor = mContentResolver.query(RawContacts.CONTENT_URI, projection,
            mCursor = mContentResolver.query(RawContacts.CONTENT_URI, CONTACTS_PROJECTION,
                    selection, selectionArgs, null);
        }

        if (mCursor == null || !mCursor.moveToFirst()) {
            if (mCursor != null) {
                try {
@@ -376,7 +444,11 @@ public class VCardComposer {
            return false;
        }

        if (mIsCallLogComposer) {
            mIdColumn = -1;
        } else {
            mIdColumn = mCursor.getColumnIndex(Contacts._ID);
        }

        return true;
    }
@@ -390,7 +462,16 @@ public class VCardComposer {
        String name = null;
        String vcard;
        try {
            if (mIsCallLogComposer) {
                vcard = createOneCallLogEntryInternal();
            } else {
                if (mIdColumn >= 0) {
                    vcard = createOneEntryInternal(mCursor.getString(mIdColumn));
                } else {
                    Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
                    return true;
                }
            }
        } catch (OutOfMemoryError error) {
            // Maybe some data (e.g. photo) is too big to have in memory. But it
            // should be rare.
@@ -422,6 +503,89 @@ public class VCardComposer {
        return true;
    }

    /**
     * Format according to RFC 2445 DATETIME type.
     * The format is: ("%Y%m%dT%H%M%S").
     */
    private final String formatDate(final long millSecs) {
        Time startDate = new Time();
        startDate.set(millSecs);
        String date = startDate.format2445();
        return date + FLAG_TIMEZONE_UTC;
    }

    /**
     * Create call history time stamp field.
     *
     * @param type call type
     */
    private String createCallHistoryTimeStampField(int type) {
        // Extension for call history as defined in
        // in the Specification for Ic Mobile Communcation - ver 1.1,
        // Oct 2000. This is used to send the details of the call
        // history - missed, incoming, outgoing along with date and time
        // to the requesting device (For example, transferring phone book
        // when connected over bluetooth)
        // X-IRMC-CALL-DATETIME;MISSED:20050320T100000
        final StringBuilder builder = new StringBuilder();
        builder.append(VCARD_PROPERTY_X_TIMESTAMP);
        builder.append(VCARD_ATTR_SEPARATOR);

        if (mIsV30) {
            builder.append(Constants.ATTR_TYPE).append(VCARD_ATTR_EQUAL);
        }

        if (type == Calls.INCOMING_TYPE) {
            builder.append("INCOMING");
        } else if (type == Calls.OUTGOING_TYPE) {
            builder.append("OUTGOING");
        } else if (type == Calls.MISSED_TYPE) {
            builder.append("MISSED");
        } else {
            Log.w(LOG_TAG, "Call log type not correct.");
            return null;
        }

        return builder.toString();
    }

    private String createOneCallLogEntryInternal() {
        final StringBuilder builder = new StringBuilder();
        appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);
        if (mIsV30) {
            appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30);
        } else {
            appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21);
        }
        String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
        if (TextUtils.isEmpty(name)) {
            name = mCursor.getString(NUMBER_COLUMN_INDEX);
        }
        boolean needCharset = !(VCardUtils.containsOnlyAscii(name));
        appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, name, needCharset, false);
        appendVCardLine(builder, VCARD_PROPERTY_NAME, name, needCharset, false);

        String number = mCursor.getString(NUMBER_COLUMN_INDEX);
        int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
        String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
        if (TextUtils.isEmpty(label)) {
            label = Integer.toString(type);
        }
        appendVCardTelephoneLine(builder, type, label, number);

        long date = mCursor.getLong(DATE_COLUMN_INDEX);
        String dateClause = formatDate(date);
        int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
        String timestampFeldString = createCallHistoryTimeStampField(callLogType);
        if (timestampFeldString != null) {
            appendVCardLine(builder, timestampFeldString, dateClause);
        }

        appendVCardLine(builder, VCARD_PROPERTY_END, VCARD_DATA_VCARD);

        return builder.toString();
    }

    private String createOneEntryInternal(final String contactId) {
        final StringBuilder builder = new StringBuilder();
        appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD);