1198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa/*
2198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * Copyright (C) 2010 The Android Open Source Project
3198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa *
4198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * use this file except in compliance with the License. You may obtain a copy of
6198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * the License at
7198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa *
8198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0
9198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa *
10198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
11198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * License for the specific language governing permissions and limitations under
14198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * the License.
15198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa */
16198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawapackage com.android.bluetooth.pbap;
17198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
1800aee7a70e3c76b6c9ef59133d59fcdc592fea99Jaikumar Ganeshimport com.android.bluetooth.R;
1977ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvallimport com.android.internal.telephony.CallerInfo;
2000aee7a70e3c76b6c9ef59133d59fcdc592fea99Jaikumar Ganesh
21198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.content.ContentResolver;
22198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.content.Context;
23198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.database.Cursor;
24198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.database.sqlite.SQLiteException;
25198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.net.Uri;
26198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog;
27198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.provider.CallLog.Calls;
28198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.text.TextUtils;
29198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.text.format.Time;
30198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport android.util.Log;
31198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
3212cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardBuilder;
3312cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardConfig;
3412cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardConstants;
3512cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawaimport com.android.vcard.VCardUtils;
3612cb33f6d9fd269944a5618661e3880beea58b6eDaisuke Miyakawa
37198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawaimport java.util.Arrays;
38198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
39198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa/**
40198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa * VCard composer especially for Call Log used in Bluetooth.
41198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa */
42198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawapublic class BluetoothPbapCallLogComposer {
43198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String TAG = "CallLogComposer";
44198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
45198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
46198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        "Failed to get database information";
47198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
48198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String FAILURE_REASON_NO_ENTRY =
49198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        "There's no exportable in the database";
50198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
51198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String FAILURE_REASON_NOT_INITIALIZED =
52198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        "The vCard composer object is not correctly initialized";
53198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
54198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    /** Should be visible only from developers... (no need to translate, hopefully) */
55198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String FAILURE_REASON_UNSUPPORTED_URI =
56198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        "The Uri vCard composer received is not supported by the composer.";
57198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
58198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String NO_ERROR = "No error";
59198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
60198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    /** The projection to use when querying the call log table */
61198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String[] sCallLogProjection = new String[] {
62198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            Calls.NUMBER, Calls.DATE, Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
63198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            Calls.CACHED_NUMBER_LABEL
64198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    };
65198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int NUMBER_COLUMN_INDEX = 0;
66198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int DATE_COLUMN_INDEX = 1;
67198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int CALL_TYPE_COLUMN_INDEX = 2;
68198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int CALLER_NAME_COLUMN_INDEX = 3;
69198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 4;
70198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 5;
71198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
72198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    // Property for call log entry
73198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
740c21a35d6d56dd42c97a80e3233df578d0a1cb21David Yue    private static final String VCARD_PROPERTY_CALLTYPE_INCOMING = "RECEIVED";
750c21a35d6d56dd42c97a80e3233df578d0a1cb21David Yue    private static final String VCARD_PROPERTY_CALLTYPE_OUTGOING = "DIALED";
76198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private static final String VCARD_PROPERTY_CALLTYPE_MISSED = "MISSED";
77198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
78198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private final Context mContext;
79198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private ContentResolver mContentResolver;
80198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private Cursor mCursor;
81198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
82198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private boolean mTerminateIsCalled;
83198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
84198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private String mErrorReason = NO_ERROR;
85198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
863c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa    public BluetoothPbapCallLogComposer(final Context context) {
87198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        mContext = context;
88198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        mContentResolver = context.getContentResolver();
89198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
90198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
91198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public boolean init(final Uri contentUri, final String selection,
92198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            final String[] selectionArgs, final String sortOrder) {
93198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final String[] projection;
94198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (CallLog.Calls.CONTENT_URI.equals(contentUri)) {
95198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            projection = sCallLogProjection;
96198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        } else {
97198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            mErrorReason = FAILURE_REASON_UNSUPPORTED_URI;
98198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            return false;
99198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
100198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
101198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        mCursor = mContentResolver.query(
102198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                contentUri, projection, selection, selectionArgs, sortOrder);
103198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
104198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor == null) {
105198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO;
106198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            return false;
107198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
108198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
109198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) {
110198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            try {
111198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                mCursor.close();
112198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            } catch (SQLiteException e) {
113198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
114198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            } finally {
115198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                mErrorReason = FAILURE_REASON_NO_ENTRY;
116198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                mCursor = null;
117198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
118198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            return false;
119198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
120198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
121198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return true;
122198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
123198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
12473adcc0f5b6051ef514a3f16a2e28eabee2b367eConley Owens    public String createOneEntry(boolean vcardVer21) {
125198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor == null || mCursor.isAfterLast()) {
126198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
1273c4d2c77c2fffe675fbe89ba58856686b6873d2fDaisuke Miyakawa            return null;
128198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
129198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        try {
13073adcc0f5b6051ef514a3f16a2e28eabee2b367eConley Owens            return createOneCallLogEntryInternal(vcardVer21);
131b7533e86bb84a2f95c2cff62c1565a8e1696d1eaDavid Yue        } finally {
132b7533e86bb84a2f95c2cff62c1565a8e1696d1eaDavid Yue            mCursor.moveToNext();
133198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
134198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
135198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
1369935a310a4f36c9f835c5c3aa2f604ddc36cabb1Xiaodong Xu    private String createOneCallLogEntryInternal(boolean vcardVer21) {
1379935a310a4f36c9f835c5c3aa2f604ddc36cabb1Xiaodong Xu        final int vcardType = (vcardVer21 ? VCardConfig.VCARD_TYPE_V21_GENERIC :
1389935a310a4f36c9f835c5c3aa2f604ddc36cabb1Xiaodong Xu                VCardConfig.VCARD_TYPE_V30_GENERIC) |
139f7df7a88230c525e2973ca5603f54a77fe47445dJaikumar Ganesh                VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING;
140f7df7a88230c525e2973ca5603f54a77fe47445dJaikumar Ganesh        final VCardBuilder builder = new VCardBuilder(vcardType);
141198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        String name = mCursor.getString(CALLER_NAME_COLUMN_INDEX);
142198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (TextUtils.isEmpty(name)) {
14377ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall            name = "";
14477ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall        }
14577ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall        if (CallerInfo.UNKNOWN_NUMBER.equals(name) || CallerInfo.PRIVATE_NUMBER.equals(name) ||
14677ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                CallerInfo.PAYPHONE_NUMBER.equals(name)) {
14777ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall            // setting name to "" as FN/N must be empty fields in this case.
14877ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall            name = "";
149198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
150198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
151198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendLine(VCardConstants.PROPERTY_FN, name, needCharset, false);
152198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendLine(VCardConstants.PROPERTY_N, name, needCharset, false);
153198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
15400aee7a70e3c76b6c9ef59133d59fcdc592fea99Jaikumar Ganesh        String number = mCursor.getString(NUMBER_COLUMN_INDEX);
15577ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall        if (CallerInfo.UNKNOWN_NUMBER.equals(number) ||
15677ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                CallerInfo.PRIVATE_NUMBER.equals(number) ||
15777ba5f6684f4dd7e4b7fc37982271da5654aec07Staffan Lindvall                CallerInfo.PAYPHONE_NUMBER.equals(number)) {
1582f429e31a13f81c9248173b144efca32c0070045Jaikumar Ganesh            number = mContext.getString(R.string.unknownNumber);
15900aee7a70e3c76b6c9ef59133d59fcdc592fea99Jaikumar Ganesh        }
160198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final int type = mCursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
161198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        String label = mCursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
162198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (TextUtils.isEmpty(label)) {
163198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            label = Integer.toString(type);
164198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
165198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendTelLine(type, label, number, false);
166198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        tryAppendCallHistoryTimeStampField(builder);
167198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
168198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return builder.toString();
169198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
170198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
171198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    /**
172198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     * This static function is to compose vCard for phone own number
173198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     */
174198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public String composeVCardForPhoneOwnNumber(int phonetype, String phoneName,
175198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            String phoneNumber, boolean vcardVer21) {
176198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final int vcardType = (vcardVer21 ?
177e05d3a710c592db386b55a265a1e657b0467e49fDaisuke Miyakawa                VCardConfig.VCARD_TYPE_V21_GENERIC :
178f7df7a88230c525e2973ca5603f54a77fe47445dJaikumar Ganesh                    VCardConfig.VCARD_TYPE_V30_GENERIC) |
179f7df7a88230c525e2973ca5603f54a77fe47445dJaikumar Ganesh                VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING;
180198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final VCardBuilder builder = new VCardBuilder(vcardType);
181198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        boolean needCharset = false;
182198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
183198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            needCharset = true;
184198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
185198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendLine(VCardConstants.PROPERTY_FN, phoneName, needCharset, false);
186198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendLine(VCardConstants.PROPERTY_N, phoneName, needCharset, false);
187198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
188198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (!TextUtils.isEmpty(phoneNumber)) {
189198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            String label = Integer.toString(phonetype);
190198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            builder.appendTelLine(phonetype, label, phoneNumber, false);
191198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
192198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
193198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return builder.toString();
194198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
195198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
196198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    /**
197198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     * Format according to RFC 2445 DATETIME type.
1981f18480dfa9ea5557bcd5928a4c152ab40b85c7eHåkan     * The format is: ("%Y%m%dT%H%M%S").
199198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     */
200198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private final String toRfc2455Format(final long millSecs) {
201198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        Time startDate = new Time();
202198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        startDate.set(millSecs);
2031f18480dfa9ea5557bcd5928a4c152ab40b85c7eHåkan        return startDate.format2445();
204198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
205198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
206198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    /**
207198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     * Try to append the property line for a call history time stamp field if possible.
208198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     * Do nothing if the call log type gotton from the database is invalid.
209198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa     */
210198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    private void tryAppendCallHistoryTimeStampField(final VCardBuilder builder) {
211198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // Extension for call history as defined in
212198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // in the Specification for Ic Mobile Communcation - ver 1.1,
213198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // Oct 2000. This is used to send the details of the call
214198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // history - missed, incoming, outgoing along with date and time
215198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // to the requesting device (For example, transferring phone book
216198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        // when connected over bluetooth)
217198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        //
2181f18480dfa9ea5557bcd5928a4c152ab40b85c7eHåkan        // e.g. "X-IRMC-CALL-DATETIME;MISSED:20050320T100000"
219198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final int callLogType = mCursor.getInt(CALL_TYPE_COLUMN_INDEX);
220198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final String callLogTypeStr;
221198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        switch (callLogType) {
222198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            case Calls.INCOMING_TYPE: {
223198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_INCOMING;
224198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                break;
225198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
226198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            case Calls.OUTGOING_TYPE: {
227198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_OUTGOING;
228198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                break;
229198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
230198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            case Calls.MISSED_TYPE: {
231198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                callLogTypeStr = VCARD_PROPERTY_CALLTYPE_MISSED;
232198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                break;
233198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
234198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            default: {
235198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                Log.w(TAG, "Call log type not correct.");
236198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                return;
237198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
238198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
239198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
240198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        final long dateAsLong = mCursor.getLong(DATE_COLUMN_INDEX);
241198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        builder.appendLine(VCARD_PROPERTY_X_TIMESTAMP,
242198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                Arrays.asList(callLogTypeStr), toRfc2455Format(dateAsLong));
243198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
244198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
245198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public void terminate() {
246198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor != null) {
247198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            try {
248198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                mCursor.close();
249198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            } catch (SQLiteException e) {
250198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa                Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
251198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            }
252198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            mCursor = null;
253198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
254198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
255198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        mTerminateIsCalled = true;
256198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
257198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
258198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    @Override
259198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public void finalize() {
260198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (!mTerminateIsCalled) {
261198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            terminate();
262198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
263198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
264198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
265198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public int getCount() {
266198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor == null) {
267198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            return 0;
268198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
269198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return mCursor.getCount();
270198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
271198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
272198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public boolean isAfterLast() {
273198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        if (mCursor == null) {
274198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa            return false;
275198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        }
276198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return mCursor.isAfterLast();
277198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
278198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa
279198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    public String getErrorReason() {
280198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa        return mErrorReason;
281198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa    }
282198e5d109571b27b7c45c30ed3ea42febcb99201Daisuke Miyakawa}
283