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

Commit 975a8594 authored by Sal Savage's avatar Sal Savage Committed by Gerrit Code Review
Browse files

Merge "Batch call log insertion operations" into main

parents 880b201d 90b792d3
Loading
Loading
Loading
Loading
+108 −44
Original line number Diff line number Diff line
@@ -224,6 +224,13 @@ class PbapClientContactsStorage {
     *
     * <p>This function also associates the phonebook metadata with the contact for easy
     * per-phonebook cleanup operations.
     *
     * <p>Contacts are inserted in smaller batches so they can be loaded in chunks as opposed to
     * shown all at once in the UI. This also prevents us from hitting the binder transaction limit.
     *
     * @param account The account to insert contacts against
     * @param phonebook The phonebook these contacts belong to
     * @param contacts The list of contacts to insert
     */
    private boolean insertContacts(Account account, String phonebook, List<VCardEntry> contacts) {
        if (!mStorageInitialized) {
@@ -374,11 +381,15 @@ class PbapClientContactsStorage {
    /**
     * Insert call history entries of a given type
     *
     * <p>These call logs are inserted in smaller batches so they can be loaded in chunks as opposed
     * to shown all at once in the UI. This also prevents us from hitting the binder transaction
     * limit
     *
     * @param account The account to insert call logs against
     * @param type The type of call history provided
     * @param history The call history to insert
     * @param type The type of call provided
     * @param history The list of calls to add
     * @return True if successful, False otherwise
     */
    @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate
    private boolean insertCallHistory(Account account, int type, List<VCardEntry> history) {
        if (!mStorageInitialized) {
            Log.w(TAG, "insertCallHistory: Failed, storage not ready");
@@ -405,18 +416,82 @@ class PbapClientContactsStorage {
        try {
            Log.i(
                    TAG,
                    "insertCallHistory: Inserting call history, type="
                    "insertCallHistory: inserting call history, account="
                            + account
                            + ", type="
                            + type
                            + ", count="
                            + history.size());

            ArrayList<ContentProviderOperation> ops = new ArrayList<>();
            for (VCardEntry vcard : history) {
            ContentResolver contactsProvider = mContext.getContentResolver();
            ArrayList<ContentProviderOperation> operations = new ArrayList<>();

            // Group insert operations together to minimize inter process communication and improve
            // processing time.
            for (VCardEntry callLog : history) {
                if (Thread.currentThread().isInterrupted()) {
                    Log.e(TAG, "insertCallHistory: Interrupted during insert");
                    break;
                }

                // Append current call to list of insert operations.
                int numberOfOperations = operations.size();
                constructInsertOperationsForCallLog(account, type, callLog, operations);

                if (operations.size() >= CONTACTS_INSERT_BATCH_SIZE) {
                    Log.i(
                            TAG,
                            "insertCallHistory: batch full, operations.size()="
                                    + operations.size()
                                    + ", batch_size="
                                    + CONTACTS_INSERT_BATCH_SIZE);

                    // If we have exceeded the limit of the insert operations, remove the latest
                    // call and submit.
                    operations.subList(numberOfOperations, operations.size()).clear();

                    contactsProvider.applyBatch(CallLog.AUTHORITY, operations);

                    // Re-add the current call log operation(s) to the list
                    operations = constructInsertOperationsForCallLog(account, type, callLog, null);

                    Log.i(
                            TAG,
                            "insertCallHistory: batch complete, operations.size()="
                                    + operations.size());
                }
            }

            // Apply any unsubmitted calls
            if (operations.size() > 0) {
                contactsProvider.applyBatch(CallLog.AUTHORITY, operations);
                operations.clear();
            }
            Log.i(TAG, "insertCallHistory: insert complete, count=" + history.size());
        } catch (OperationApplicationException | RemoteException | NumberFormatException e) {
            Log.e(TAG, "insertCallHistory: Exception occurred while processing call log pull: ", e);
            return false;
        }
        return true;
    }

    // TODO: b/365629730 -- JavaUtilDate: prefer Instant or LocalDate
    // NonApiType: For convenience, as the applyBatch API actually takes an ArrayList above
    @SuppressWarnings({"JavaUtilDate", "NonApiType"})
    private ArrayList<ContentProviderOperation> constructInsertOperationsForCallLog(
            Account account,
            int type,
            VCardEntry call,
            ArrayList<ContentProviderOperation> operations) {
        if (operations == null) {
            operations = new ArrayList<ContentProviderOperation>();
        }

        ContentValues values = new ContentValues();
                values.put(CallLog.Calls.TYPE, type);
        values.put(Calls.PHONE_ACCOUNT_ID, account.name);
        values.put(CallLog.Calls.TYPE, type);

                List<PhoneData> phones = vcard.getPhoneList();
        List<PhoneData> phones = call.getPhoneList();
        if (phones == null
                || phones.get(0).getNumber().equals(";")
                || phones.get(0).getNumber().length() == 0) {
@@ -426,7 +501,7 @@ class PbapClientContactsStorage {
            values.put(CallLog.Calls.NUMBER, phoneNumber);
        }

                List<Pair<String, String>> irmc = vcard.getUnknownXData();
        List<Pair<String, String>> irmc = call.getUnknownXData();
        SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT);
        if (irmc != null) {
            for (Pair<String, String> pair : irmc) {
@@ -440,24 +515,13 @@ class PbapClientContactsStorage {
            }
        }

                ops.add(
        operations.add(
                ContentProviderOperation.newInsert(CallLog.Calls.CONTENT_URI)
                        .withValues(values)
                        .withYieldAllowed(true)
                        .build());
            }

            mContext.getContentResolver().applyBatch(CallLog.AUTHORITY, ops);
            Log.d(TAG, "Inserted call logs, type=" + type);
        } catch (RemoteException | OperationApplicationException e) {
            Log.w(TAG, "Failed to insert call log, type=" + type, e);
            return false;
        } finally {
            synchronized (this) {
                this.notify();
            }
        }
        return true;
        return operations;
    }

    /**