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

Commit 7c32a210 authored by Andrew Cheng's avatar Andrew Cheng Committed by Gerrit Code Review
Browse files

Merge "Switch VCardParser version if it doesn't match vCard version" into main

parents 62f444e4 7fdd913c
Loading
Loading
Loading
Loading
+56 −6
Original line number Diff line number Diff line
@@ -17,22 +17,27 @@
package com.android.bluetooth.pbapclient;

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

import com.android.vcard.VCardConfig;
import com.android.vcard.VCardEntry;
import com.android.vcard.VCardEntryConstructor;
import com.android.vcard.VCardEntryCounter;
import com.android.vcard.VCardEntryHandler;
import com.android.vcard.VCardParser;
import com.android.vcard.VCardParser_V21;
import com.android.vcard.VCardParser_V30;
import com.android.vcard.exception.VCardException;
import com.android.vcard.exception.VCardVersionException;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

class BluetoothPbapVcardList {
    private static final String TAG = BluetoothPbapVcardList.class.getSimpleName();
    // {@link BufferedInputStream#DEFAULT_BUFFER_SIZE} is not public
    private static final int BIS_DEFAULT_BUFFER_SIZE = 8192;

    private final ArrayList<VCardEntry> mCards = new ArrayList<VCardEntry>();
    private final Account mAccount;
@@ -53,6 +58,10 @@ class BluetoothPbapVcardList {
    }

    BluetoothPbapVcardList(Account account, InputStream in, byte format) throws IOException {
        if (format != PbapClientConnectionHandler.VCARD_TYPE_21
                && format != PbapClientConnectionHandler.VCARD_TYPE_30) {
            throw new IllegalArgumentException("Unsupported vCard version.");
        }
        mAccount = account;
        parse(in, format);
    }
@@ -68,19 +77,60 @@ class BluetoothPbapVcardList {

        VCardEntryConstructor constructor =
                new VCardEntryConstructor(VCardConfig.VCARD_TYPE_V21_GENERIC, mAccount);
        VCardEntryCounter counter = new VCardEntryCounter();
        CardEntryHandler handler = new CardEntryHandler();

        CardEntryHandler handler = new CardEntryHandler();
        constructor.addEntryHandler(handler);

        parser.addInterpreter(constructor);
        parser.addInterpreter(counter);

        // {@link BufferedInputStream} supports the {@link InputStream#mark} and
        // {@link InputStream#reset} methods.
        BufferedInputStream bufferedInput = new BufferedInputStream(in);
        bufferedInput.mark(BIS_DEFAULT_BUFFER_SIZE /* readlimit */);

        // If there is a {@link VCardVersionException}, try parsing again with a different
        // version. Otherwise, parsing either succeeds (i.e., no {@link VCardException}) or it
        // 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) {
                parser = new VCardParser_V30();
                Log.w(TAG, "vCard version and Parser mismatch; expected v2.1, switching to v3.0");
            } else {
                parser = new VCardParser_V21();
                Log.w(TAG, "vCard version and Parser mismatch; expected v3.0, switching to v2.1");
            }
            // reset and try again
            bufferedInput.reset();
            mCards.clear();
            constructor.clear();
            parser.addInterpreter(constructor);
            if (parsedWithVcardVersionException(parser, bufferedInput)) {
                Log.e(TAG, "unsupported vCard version, neither v2.1 nor v3.0");
            }
        }
    }

    /**
     * Attempts to parse, with an eye on whether the correct version of Parser is used.
     *
     * @param parser -- the {@link VCardParser} to use.
     * @param in -- the {@link InputStream} to parse.
     * @return {@code true} if there was a {@link VCardVersionException}; {@code false} if there
     *         is any other {@link VCardException} or succeeds (i.e., no {@link VCardException}).
     * @throws IOException if there's an issue reading the {@link InputStream}.
     */
    private boolean parsedWithVcardVersionException(VCardParser parser, InputStream in)
            throws IOException {
        try {
            parser.parse(in);
        } catch (VCardException e) {
            e.printStackTrace();
        } catch (VCardVersionException e1) {
            Log.w(TAG, "vCard version and Parser mismatch", e1);
            return true;
        } catch (VCardException e2) {
            Log.e(TAG, "vCard exception", e2);
        }
        return false;
    }

    public int getCount() {
+6 −2
Original line number Diff line number Diff line
@@ -435,7 +435,9 @@ class PbapClientConnectionHandler extends Handler {
                Log.w(TAG, "Download contacts incomplete, index exceeded upper limit.");
            }
        } catch (IOException e) {
            Log.w(TAG, "Download contacts failure" + e.toString());
            Log.e(TAG, "Download contacts failure", e);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Download contacts failure: " + e.getMessage(), e);
        }
    }

@@ -451,7 +453,9 @@ class PbapClientConnectionHandler extends Handler {
            processor.setResults(request.getList());
            processor.onPullComplete();
        } catch (IOException e) {
            Log.w(TAG, "Download call log failure");
            Log.e(TAG, "Download call log failure", e);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Download call log failure: " + e.getMessage(), e);
        }
    }

+10 −0
Original line number Diff line number Diff line
BEGIN:VCARD
VERSION:googol
FN:Jean Dupont
N:Dupont;Jean
ADR;WORK;QUOTED-PRINTABLE:;Paris 75010;91 Rue du Faubourg Saint-
Martin
TEL;CELL;PREF:+1234 56789
EMAIL;INTERNET:jean.dupont@example.com
X-BT-UID:A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
END:VCARD
+10 −0
Original line number Diff line number Diff line
BEGIN:VCARD
VERSION:2.1
FN:Jean Dupont
N:Dupont;Jean
ADR;WORK;QUOTED-PRINTABLE:;Paris 75010;91 Rue du Faubourg Saint-
Martin
TEL;CELL;PREF:+1234 56789
EMAIL;INTERNET:jean.dupont@example.com
X-BT-UID:A1A2A3A4B1B2C1C2D1D2E1E2E3E4E5E6
END:VCARD
+18 −2
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ public class BluetoothPbapRequestPullPhoneBookTest {
    }

    @Test
    public void readResponse_failWithMockInputStream() {
    public void readResponse_failWithInputStreamThatThrowsIOEWhenRead() {
        final long filter = 1;
        final byte format = 0; // Will be properly handled as VCARD_TYPE_21.
        final int maxListCount = 0; // Will be specially handled as 65535.
@@ -77,7 +77,23 @@ public class BluetoothPbapRequestPullPhoneBookTest {
        BluetoothPbapRequestPullPhoneBook request = new BluetoothPbapRequestPullPhoneBook(
                PB_NAME, ACCOUNT, filter, format, maxListCount, listStartOffset);

        InputStream is = mock(InputStream.class);
        final InputStream is = new InputStream() {
            @Override
            public int read() throws IOException {
                throw new IOException();
            }

            @Override
            public int read(byte[] b) throws IOException {
                throw new IOException();
            }

            @Override
            public int read(byte[] b, int off, int len) throws IOException {
                throw new IOException();
            }
        };

        assertThrows(IOException.class, () -> request.readResponse(is));
    }

Loading