1b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo/* 2b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Copyright (C) 2016 The Android Open Source Project 3b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 4b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Licensed under the Apache License, Version 2.0 (the "License"); 5b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * you may not use this file except in compliance with the License. 6b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * You may obtain a copy of the License at 7b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 8b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * http://www.apache.org/licenses/LICENSE-2.0 9b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * 10b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * Unless required by applicable law or agreed to in writing, software 11b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * distributed under the License is distributed on an "AS IS" BASIS, 12b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * See the License for the specific language governing permissions and 14b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo * limitations under the License. 15b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo */ 16b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzopackage com.android.bluetooth.pbapclient; 17b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 18b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport com.android.bluetooth.pbapclient.BluetoothPbapClient; 19b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.content.ContentProviderOperation; 20b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.content.ContentValues; 21b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.content.Context; 22b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.content.OperationApplicationException; 23b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.os.RemoteException; 24b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.provider.CallLog; 25b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.util.Log; 26b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport android.util.Pair; 27b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 28b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport com.android.vcard.VCardEntry; 29b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport com.android.vcard.VCardEntry.PhoneData; 30b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 31b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.text.ParseException; 32b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.text.SimpleDateFormat; 33b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.util.ArrayList; 34b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.util.Date; 35b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzoimport java.util.List; 36b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 37b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzopublic class CallLogPullRequest extends PullRequest { 38b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static boolean DBG = true; 39b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static String TAG = "PbapCallLogPullRequest"; 40b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final String TIMESTAMP_PROPERTY = "X-IRMC-CALL-DATETIME"; 41b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private static final String TIMESTAMP_FORMAT = "yyyyMMdd'T'HHmmss"; 42b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 43b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo private Context mContext; 44b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 45b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo public CallLogPullRequest(Context context, String path) { 46b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mContext = context; 47b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo this.path = path; 48b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 49b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 50b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo @Override 517a3cfba99e1e99c937901fb1695c97b954f34121Joseph Pirozzo public void onPullComplete() { 527a3cfba99e1e99c937901fb1695c97b954f34121Joseph Pirozzo if (mEntries == null) { 53b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.e(TAG, "onPullComplete entries is null."); 54b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return; 55b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 56b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 57b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (DBG) { 587a3cfba99e1e99c937901fb1695c97b954f34121Joseph Pirozzo Log.d(TAG, "onPullComplete with " + mEntries.size() + " count."); 59b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 60b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo int type; 61b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 62b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (path.equals(BluetoothPbapClient.ICH_PATH)) { 63b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo type = CallLog.Calls.INCOMING_TYPE; 64b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } else if (path.equals(BluetoothPbapClient.OCH_PATH)) { 65b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo type = CallLog.Calls.OUTGOING_TYPE; 66b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } else if (path.equals(BluetoothPbapClient.MCH_PATH)) { 67b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo type = CallLog.Calls.MISSED_TYPE; 68b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } else { 69b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.w(TAG, "Unknown path type:" + path); 70b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo return; 71b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 72b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 73b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo ArrayList<ContentProviderOperation> ops = new ArrayList<>(); 747a3cfba99e1e99c937901fb1695c97b954f34121Joseph Pirozzo for (VCardEntry vcard : mEntries) { 75b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo List<PhoneData> phones = vcard.getPhoneList(); 76b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (phones == null || phones.size() != 1) { 77b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Incorrect number of phones: " + vcard); 78b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo continue; 79b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 80b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 81b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo List<Pair<String, String>> irmc = vcard.getUnknownXData(); 82b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Date date = null; 83b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT); 84b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo for (Pair<String, String> pair : irmc) { 85b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (pair.first.startsWith(TIMESTAMP_PROPERTY)) { 86b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo try { 87b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo date = parser.parse(pair.second); 88b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (ParseException e) { 89b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Failed to parse date " + pair.second); 90b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 91b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 92b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 93b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo 94b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo ContentValues values = new ContentValues(); 95b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo values.put(CallLog.Calls.TYPE, type); 96b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo values.put(CallLog.Calls.NUMBER, phones.get(0).getNumber()); 97b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo if (date != null) { 98b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo values.put(CallLog.Calls.DATE, date.getTime()); 99b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 100b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo ops.add(ContentProviderOperation.newInsert(CallLog.Calls.CONTENT_URI) 101b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo .withValues(values).withYieldAllowed(true).build()); 102b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 103b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo mContext.getContentResolver().applyBatch(CallLog.AUTHORITY, ops); 104b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Updated call logs."); 105b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } catch (RemoteException | OperationApplicationException e) { 106b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo Log.d(TAG, "Failed to update call log for path=" + path, e); 107b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } finally { 108b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo synchronized (this) { 109b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo this.notify(); 110b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 111b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 112b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo } 113b874a1d1cf25f90947ba87f791d42a404cad7d85Joseph Pirozzo} 114