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

Commit 4f2d3c8d authored by Sal Savage's avatar Sal Savage
Browse files

Rename PbapClientVcardList to PbapPhonebook and update test coverage

This change migrates the VcardList object to be a more generic
"Phonebook" object, which can also own constants related to the
phonebook concept in PBAP, like the path names.

Additional test coverage was added for PbapPhonebook. This object owns
VCard parsing, so parse tests were moved to this object as well,
removing the need for a parser specific test.

Bug: 365626536
Flag: EXEMPT, mechanical refactor with no logic changes + test coverage
Test: atest com.android.bluetooth.pbapclient
Test: m com.android.btservices
Change-Id: I9a8896c6aaccf7e6f972c658625189d3efac5f5f
parent b039eb97
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -69,11 +69,11 @@ public class CallLogPullRequest extends PullRequest {
        Log.d(TAG, "onPullComplete with " + mEntries.size() + " entries");
        int type;
        try {
            if (path.equals(PbapClientConnectionHandler.ICH_PATH)) {
            if (path.equals(PbapPhonebook.ICH_PATH)) {
                type = CallLog.Calls.INCOMING_TYPE;
            } else if (path.equals(PbapClientConnectionHandler.OCH_PATH)) {
            } else if (path.equals(PbapPhonebook.OCH_PATH)) {
                type = CallLog.Calls.OUTGOING_TYPE;
            } else if (path.equals(PbapClientConnectionHandler.MCH_PATH)) {
            } else if (path.equals(PbapPhonebook.MCH_PATH)) {
                type = CallLog.Calls.MISSED_TYPE;
            } else {
                Log.w(TAG, "Unknown path type:" + path);
+13 −24
Original line number Diff line number Diff line
@@ -113,24 +113,12 @@ class PbapClientConnectionHandler extends Handler {

    @VisibleForTesting static final int L2CAP_INVALID_PSM = -1;

    public static final String PB_PATH = "telecom/pb.vcf";
    public static final String FAV_PATH = "telecom/fav.vcf";
    public static final String MCH_PATH = "telecom/mch.vcf";
    public static final String ICH_PATH = "telecom/ich.vcf";
    public static final String OCH_PATH = "telecom/och.vcf";
    public static final String SIM_PB_PATH = "SIM1/telecom/pb.vcf";
    public static final String SIM_MCH_PATH = "SIM1/telecom/mch.vcf";
    public static final String SIM_ICH_PATH = "SIM1/telecom/ich.vcf";
    public static final String SIM_OCH_PATH = "SIM1/telecom/och.vcf";

    // PBAP v1.2.3 Sec. 7.1.2
    private static final int SUPPORTED_REPOSITORIES_LOCALPHONEBOOK = 1 << 0;
    private static final int SUPPORTED_REPOSITORIES_SIMCARD = 1 << 1;
    private static final int SUPPORTED_REPOSITORIES_FAVORITES = 1 << 3;

    public static final int PBAP_V1_2 = 0x0102;
    public static final byte VCARD_TYPE_21 = 0;
    public static final byte VCARD_TYPE_30 = 1;

    private Account mAccount;
    private AccountManager mAccountManager;
@@ -250,19 +238,19 @@ class PbapClientConnectionHandler extends Handler {
                    return;
                }
                if (isRepositorySupported(SUPPORTED_REPOSITORIES_FAVORITES)) {
                    downloadContacts(FAV_PATH);
                    downloadContacts(PbapPhonebook.FAVORITES_PATH);
                }
                if (isRepositorySupported(SUPPORTED_REPOSITORIES_LOCALPHONEBOOK)) {
                    downloadContacts(PB_PATH);
                    downloadContacts(PbapPhonebook.LOCAL_PHONEBOOK_PATH);
                }
                if (isRepositorySupported(SUPPORTED_REPOSITORIES_SIMCARD)) {
                    downloadContacts(SIM_PB_PATH);
                    downloadContacts(PbapPhonebook.SIM_PHONEBOOK_PATH);
                }

                Map<String, Integer> callCounter = new HashMap<>();
                downloadCallLog(MCH_PATH, callCounter);
                downloadCallLog(ICH_PATH, callCounter);
                downloadCallLog(OCH_PATH, callCounter);
                downloadCallLog(PbapPhonebook.MCH_PATH, callCounter);
                downloadCallLog(PbapPhonebook.ICH_PATH, callCounter);
                downloadCallLog(PbapPhonebook.OCH_PATH, callCounter);
                break;

            default:
@@ -388,7 +376,7 @@ class PbapClientConnectionHandler extends Handler {

            int numberOfContactsRemaining = requestPbSize.getSize();
            int startOffset = 0;
            if (PB_PATH.equals(path)) {
            if (PbapPhonebook.LOCAL_PHONEBOOK_PATH.equals(path)) {
                // PBAP v1.2.3, Sec 3.1.5. The first contact in pb is owner card 0.vcf, which we
                // do not want to download. The other phonebook objects (e.g., fav) don't have an
                // owner card, so they don't need an offset.
@@ -405,14 +393,14 @@ class PbapClientConnectionHandler extends Handler {
                RequestPullPhoneBook request =
                        new RequestPullPhoneBook(
                                path,
                                mAccount,
                                PBAP_REQUESTED_FIELDS,
                                VCARD_TYPE_30,
                                PbapPhonebook.FORMAT_VCARD_30,
                                numberOfContactsToDownload,
                                startOffset);
                                startOffset,
                                mAccount);
                request.execute(mObexSession);
                List<VCardEntry> vcards = request.getList();
                if (FAV_PATH.equals(path)) {
                if (PbapPhonebook.FAVORITES_PATH.equals(path)) {
                    // mark each vcard as a favorite
                    for (VCardEntry v : vcards) {
                        v.setStarred(true);
@@ -438,7 +426,8 @@ class PbapClientConnectionHandler extends Handler {
    void downloadCallLog(String path, Map<String, Integer> callCounter) {
        try {
            RequestPullPhoneBook request =
                    new RequestPullPhoneBook(path, mAccount, 0, VCARD_TYPE_30, 0, 0);
                    new RequestPullPhoneBook(
                            path, 0, PbapPhonebook.FORMAT_VCARD_30, 0, 0, mAccount);
            request.execute(mObexSession);
            CallLogPullRequest processor =
                    new CallLogPullRequest(
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ abstract class PbapClientRequest {
    protected static final byte OAP_TAGID_SEARCH_ATTRIBUTE = 0x03;
    protected static final byte OAP_TAGID_MAX_LIST_COUNT = 0x04;
    protected static final byte OAP_TAGID_LIST_START_OFFSET = 0x05;
    protected static final byte OAP_TAGID_FILTER = 0x06;
    protected static final byte OAP_TAGID_PROPERTY_SELECTOR = 0x06;
    protected static final byte OAP_TAGID_FORMAT = 0x07;
    protected static final byte OAP_TAGID_PHONEBOOK_SIZE = 0x08;
    protected static final byte OAP_TAGID_NEW_MISSED_CALLS = 0x09;
+79 −11
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.bluetooth.pbapclient;

import android.accounts.Account;
import android.annotation.Nullable;
import android.util.Log;

import com.android.vcard.VCardConfig;
@@ -35,13 +36,36 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

class PbapClientVcardList {
    private static final String TAG = PbapClientVcardList.class.getSimpleName();
public class PbapPhonebook {
    private static final String TAG = PbapPhonebook.class.getSimpleName();

    // {@link BufferedInputStream#DEFAULT_BUFFER_SIZE} is not public
    private static final int BIS_DEFAULT_BUFFER_SIZE = 8192;

    // Phonebooks, including call history. See PBAP 1.2.3, Section 3.1.2
    public static final String LOCAL_PHONEBOOK_PATH = "telecom/pb.vcf"; // Device phonebook
    public static final String FAVORITES_PATH = "telecom/fav.vcf"; // Contacts marked as favorite
    public static final String MCH_PATH = "telecom/mch.vcf"; // Missed Calls
    public static final String ICH_PATH = "telecom/ich.vcf"; // Incoming Calls
    public static final String OCH_PATH = "telecom/och.vcf"; // Outgoing Calls
    public static final String SIM_PHONEBOOK_PATH = "SIM1/telecom/pb.vcf"; // SIM stored phonebook
    public static final String SIM_MCH_PATH = "SIM1/telecom/mch.vcf"; // SIM stored Missed Calls
    public static final String SIM_ICH_PATH = "SIM1/telecom/ich.vcf"; // SIM stored Incoming Calls
    public static final String SIM_OCH_PATH = "SIM1/telecom/och.vcf"; // SIM stored Outgoing Calls

    // VCard Formats, both are required to be supported by the Server, PBAP 1.2.3, Section 5.1.4.2
    public static byte FORMAT_VCARD_21 = 0;
    public static byte FORMAT_VCARD_30 = 1;

    private final String mPhonebook;
    private final int mListStartOffset;
    private final List<VCardEntry> mCards = new ArrayList<VCardEntry>();
    private final Account mAccount;

    // Needed for VCard parsing, since the account on older platform versions cannot be associated
    // with the VCard (to construct a query) after parse time. Newer platform versions support this
    // though, which means we can eventually remove this in favor of assigning an account post parse
    // time.
    @Nullable private final Account mAccount;

    class CardEntryHandler implements VCardEntryHandler {
        @Override
@@ -56,19 +80,32 @@ class PbapClientVcardList {
        public void onEnd() {}
    }

    PbapClientVcardList(Account account, InputStream in, byte format) throws IOException {
        if (format != PbapClientConnectionHandler.VCARD_TYPE_21
                && format != PbapClientConnectionHandler.VCARD_TYPE_30) {
    PbapPhonebook(String phonebook) {
        mPhonebook = phonebook;
        mAccount = null;
        mListStartOffset = 0;
    }

    PbapPhonebook(
            String phonebook,
            byte format,
            int listStartOffset,
            @Nullable Account account,
            InputStream inputStream)
            throws IOException {
        if (format != FORMAT_VCARD_21 && format != FORMAT_VCARD_30) {
            throw new IllegalArgumentException("Unsupported vCard version.");
        }
        mPhonebook = phonebook;
        mListStartOffset = listStartOffset;
        mAccount = account;
        parse(in, format);
        parse(inputStream, format);
    }

    private void parse(InputStream in, byte format) throws IOException {
        VCardParser parser;

        if (format == PbapClientConnectionHandler.VCARD_TYPE_30) {
        if (format == FORMAT_VCARD_30) {
            parser = new VCardParser_V30();
        } else {
            parser = new VCardParser_V21();
@@ -92,7 +129,7 @@ class PbapClientVcardList {
        // fails with a different {@link VCardException}.
        if (parsedWithVcardVersionException(parser, bufferedInput)) {
            // PBAP v1.2.3 only supports vCard versions 2.1 and 3.0; it's one or the other
            if (format == PbapClientConnectionHandler.VCARD_TYPE_21) {
            if (format == FORMAT_VCARD_21) {
                parser = new VCardParser_V30();
                Log.w(TAG, "vCard version and Parser mismatch; expected v2.1, switching to v3.0");
            } else {
@@ -132,15 +169,46 @@ class PbapClientVcardList {
        return false;
    }

    /**
     * Get the phonebook path associated with this PbapPhonebook object
     *
     * @return a string representing the path these VCard objects were requested from
     */
    public String getPhonebook() {
        return mPhonebook;
    }

    /**
     * Get the offset associated with this PbapPhonebook object
     *
     * <p>The offset respresents the start index of the remote contacts pull
     *
     * @return an int representing the offset index where this pull started from
     */
    public int getOffset() {
        return mListStartOffset;
    }

    /**
     * Get the total number of contacts contained in this phonebook
     *
     * @return an int containing the total number of contacts contained in this phonebook
     */
    public int getCount() {
        return mCards.size();
    }

    /**
     * Get the list of VCard objects contained in this phonebook
     *
     * @return a list of VCard objects in this phonebook
     */
    public List<VCardEntry> getList() {
        return mCards;
    }

    public VCardEntry getFirst() {
        return mCards.get(0);
    @Override
    public String toString() {
        return "<" + TAG + "phonebook=" + mPhonebook + " entries=" + getCount() + ">";
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public class PhonebookPullRequest extends PullRequest {

    public PhonebookPullRequest(Context context) {
        mContext = context;
        path = PbapClientConnectionHandler.PB_PATH;
        path = PbapPhonebook.LOCAL_PHONEBOOK_PATH;
    }

    @Override
Loading