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

Commit 876cbebc authored by Hyundo Moon's avatar Hyundo Moon Committed by Automerger Merge Worker
Browse files

Merge changes from topic "cherrypicker-L12400000957513984:N30500001315227278"...

Merge changes from topic "cherrypicker-L12400000957513984:N30500001315227278" into tm-qpr-dev am: 818a3830

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/20571228



Change-Id: I36306cab94b8640b9afc5490573b2558998bb946
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 6f99b6e9 818a3830
Loading
Loading
Loading
Loading
+78 −69
Original line number Diff line number Diff line
@@ -315,7 +315,7 @@ public class BluetoothPbapVcardManager {

    final ArrayList<String> getSelectedPhonebookNameList(final int orderByWhat,
            final boolean vcardType21, int needSendBody, int pbSize, byte[] selector,
            String vcardselectorop) {
            String vCardSelectorOperator) {
        ArrayList<String> nameList = new ArrayList<String>();
        PropertySelector vcardselector = new PropertySelector(selector);
        VCardComposer composer = null;
@@ -389,13 +389,13 @@ public class BluetoothPbapVcardManager {
                        Log.v(TAG, "Checking selected bits in the vcard composer" + vcard);
                    }

                    if (!vcardselector.checkVCardSelector(vcard, vcardselectorop)) {
                    if (!vcardselector.checkVCardSelector(vcard, vCardSelectorOperator)) {
                        Log.e(TAG, "vcard selector check fail");
                        vcard = null;
                        pbSize--;
                        continue;
                    } else {
                        String name = vcardselector.getName(vcard);
                        String name = getNameFromVCard(vcard);
                        if (TextUtils.isEmpty(name)) {
                            name = mContext.getString(android.R.string.unknownName);
                        }
@@ -657,14 +657,14 @@ public class BluetoothPbapVcardManager {
    /**
     * Filter contact cursor by certain condition.
     */
    private static final class ContactCursorFilter {
    static final class ContactCursorFilter {
        /**
         *
         * @param contactCursor
         * @param offset
         * @return a cursor containing contact id of {@code offset} contact.
         */
        public static Cursor filterByOffset(Cursor contactCursor, int offset) {
        static Cursor filterByOffset(Cursor contactCursor, int offset) {
            return filterByRange(contactCursor, offset, offset);
        }

@@ -674,9 +674,9 @@ public class BluetoothPbapVcardManager {
         * @param startPoint
         * @param endPoint
         * @return a cursor containing contact ids of {@code startPoint}th to {@code endPoint}th
         * contact.
         * contact. (i.e. [startPoint, endPoint], both points should be greater than 0)
         */
        public static Cursor filterByRange(Cursor contactCursor, int startPoint, int endPoint) {
        static Cursor filterByRange(Cursor contactCursor, int startPoint, int endPoint) {
            final int contactIdColumn = contactCursor.getColumnIndex(Data.CONTACT_ID);
            long previousContactId = -1;
            // As startPoint, endOffset index starts from 1 to n, we set
@@ -1090,7 +1090,7 @@ public class BluetoothPbapVcardManager {
            if (vCardType21 && bit.excludeForV21) {
                return false;
            }
            if (mFilter == null || offset >= mFilter.length) {
            if (mFilter == null || offset > mFilter.length) {
                return true;
            }
            return ((mFilter[mFilter.length - offset] >> bitPos) & 0x01) != 0;
@@ -1147,7 +1147,8 @@ public class BluetoothPbapVcardManager {
        }
    }

    private static class PropertySelector {
    @VisibleForTesting
    static class PropertySelector {
        private enum PropertyMask {
            //               bit    property
            VERSION(0, "VERSION"),
@@ -1166,12 +1167,12 @@ public class BluetoothPbapVcardManager {
            NICKNAME(23, "NICKNAME"),
            DATETIME(28, "DATETIME");

            public final int pos;
            public final String prop;
            public final int mBitPosition;
            public final String mProperty;

            PropertyMask(int pos, String prop) {
                this.pos = pos;
                this.prop = prop;
            PropertyMask(int bitPosition, String property) {
                this.mBitPosition = bitPosition;
                this.mProperty = property;
            }
        }

@@ -1182,71 +1183,51 @@ public class BluetoothPbapVcardManager {
            this.mSelector = selector;
        }

        private boolean checkbit(int attrBit, byte[] selector) {
            int selectorlen = selector.length;
            if (((selector[selectorlen - 1 - ((int) attrBit / 8)] >> (attrBit % 8)) & 0x01) == 0) {
                return false;
            }
            return true;
        }
        boolean checkVCardSelector(String vCard, String vCardSelectorOperator) {
            Log.d(TAG, "vCardSelectorOperator=" + vCardSelectorOperator);

        private boolean checkprop(String vcard, String prop) {
            String[] lines = vcard.split(SEPARATOR);
            boolean isPresent = false;
            for (String line : lines) {
                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
                    String currentProp = line.split("[;:]")[0];
                    if (prop.equals(currentProp)) {
                        Log.d(TAG, "bit.prop.equals current prop :" + prop);
                        isPresent = true;
                        return isPresent;
                    }
                }
            }
            final boolean checkAtLeastOnePropertyExists = vCardSelectorOperator.equals("0");
            final boolean checkAllPropertiesExist = vCardSelectorOperator.equals("1");

            return isPresent;
        }
            boolean result = true;

        private boolean checkVCardSelector(String vcard, String vcardselectorop) {
            boolean selectedIn = true;
            if (checkAtLeastOnePropertyExists) {
                for (PropertyMask mask : PropertyMask.values()) {
                    if (!checkBit(mask.mBitPosition, mSelector)) {
                        continue;
                    }
                    Log.d(TAG, "checking for prop :" + mask.mProperty);

            for (PropertyMask bit : PropertyMask.values()) {
                if (checkbit(bit.pos, mSelector)) {
                    Log.d(TAG, "checking for prop :" + bit.prop);
                    if (vcardselectorop.equals("0")) {
                        if (checkprop(vcard, bit.prop)) {
                            Log.d(TAG, "bit.prop.equals current prop :" + bit.prop);
                            selectedIn = true;
                            break;
                    if (doesVCardHaveProperty(vCard, mask.mProperty)) {
                        Log.d(TAG, "mask.prop.equals current prop :" + mask.mProperty);
                        return true;
                    } else {
                            selectedIn = false;
                        result = false;
                    }
                    } else if (vcardselectorop.equals("1")) {
                        if (!checkprop(vcard, bit.prop)) {
                            Log.d(TAG, "bit.prop.notequals current prop" + bit.prop);
                            selectedIn = false;
                            return selectedIn;
                        } else {
                            selectedIn = true;
                }
            } else if (checkAllPropertiesExist) {
                for (PropertyMask mask : PropertyMask.values()) {
                    if (!checkBit(mask.mBitPosition, mSelector)) {
                        continue;
                    }
                    Log.d(TAG, "checking for prop :" + mask.mProperty);

                    if (!doesVCardHaveProperty(vCard, mask.mProperty)) {
                        Log.d(TAG, "mask.prop.notequals current prop" + mask.mProperty);
                        return false;
                    }
                }
            return selectedIn;
            }

        private String getName(String vcard) {
            String[] lines = vcard.split(SEPARATOR);
            String name = "";
            for (String line : lines) {
                if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
                    if (line.startsWith("N:")) {
                        name = line.substring(line.lastIndexOf(':'), line.length());
            return result;
        }

        private boolean checkBit(int attrBit, byte[] selector) {
            int offset = (attrBit / 8) + 1;
            if (mSelector == null || offset > mSelector.length) {
                return false;
            }
            }
            Log.d(TAG, "returning name: " + name);
            return name;
            return ((selector[mSelector.length - offset] >> (attrBit % 8)) & 0x01) != 0;
        }
    }

@@ -1307,4 +1288,32 @@ public class BluetoothPbapVcardManager {
            }
        }
    }

    @VisibleForTesting
    static String getNameFromVCard(String vCard) {
        String[] lines = vCard.split(PropertySelector.SEPARATOR);
        String name = "";
        for (String line : lines) {
            if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
                if (line.startsWith("N:")) {
                    name = line.substring(line.lastIndexOf(':') + 1);
                }
            }
        }
        Log.d(TAG, "returning name: " + name);
        return name;
    }

    private static boolean doesVCardHaveProperty(String vCard, String property) {
        String[] lines = vCard.split(PropertySelector.SEPARATOR);
        for (String line : lines) {
            if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) {
                String currentProperty = line.split("[;:]")[0];
                if (property.equals(currentProperty)) {
                    return true;
                }
            }
        }
        return false;
    }
}
+216 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.pbap;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.provider.ContactsContract;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.pbap.BluetoothPbapVcardManager.ContactCursorFilter;
import com.android.bluetooth.pbap.BluetoothPbapVcardManager.PropertySelector;
import com.android.bluetooth.pbap.BluetoothPbapVcardManager.VCardFilter;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.concurrent.atomic.AtomicInteger;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BluetoothPbapVcardManagerNestedClassesTest {

    @Mock
    Context mContext;

    @Mock
    Resources mResources;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        when(mContext.getResources()).thenReturn(mResources);
    }

    @Test
    public void VCardFilter_isPhotoEnabled_whenFilterIncludesPhoto_returnsTrue() {
        final byte photoEnableBit = 1 << 3;
        byte[] filter = new byte[] {photoEnableBit};
        VCardFilter vCardFilter = new VCardFilter(filter);

        assertThat(vCardFilter.isPhotoEnabled()).isTrue();
    }

    @Test
    public void VCardFilter_isPhotoEnabled_whenFilterExcludesPhoto_returnsFalse() {
        byte[] filter = new byte[] {(byte) 0x00};
        VCardFilter vCardFilter = new VCardFilter(filter);

        assertThat(vCardFilter.isPhotoEnabled()).isFalse();
    }

    @Test
    public void VCardFilter_apply_whenFilterIsNull_returnsSameVcard() {
        VCardFilter vCardFilter = new VCardFilter(/*filter=*/null);

        String vCard = "FN:Full Name";
        assertThat(vCardFilter.apply(vCard, /*vCardType21=*/ true)).isEqualTo(vCard);
    }

    @Test
    public void VCardFilter_apply_returnsSameVcard() {
        final String separator = System.getProperty("line.separator");
        String vCard = "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator
                + "X-IRMC-CALL-DATETIME:20170314T173942" + separator;

        byte[] emailExcludeFilter = new byte[] {(byte) 0xFE, (byte) 0xFF};
        VCardFilter vCardFilter = new VCardFilter(/*filter=*/ emailExcludeFilter);
        String expectedVCard = "FN:Test Full Name" + separator
                + "X-IRMC-CALL-DATETIME:20170314T173942" + separator;

        assertThat(vCardFilter.apply(vCard, /*vCardType21=*/ true))
                .isEqualTo(expectedVCard);
    }

    @Test
    public void PropertySelector_checkVCardSelector_atLeastOnePropertyExists_returnsTrue() {
        final String separator = System.getProperty("line.separator");
        String vCard = "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator
                + "TEL:0123456789" + separator;

        byte[] emailSelector = new byte[] {0x01, 0x00};
        PropertySelector selector = new PropertySelector(emailSelector);

        assertThat(selector.checkVCardSelector(vCard, "0")).isTrue();
    }

    @Test
    public void PropertySelector_checkVCardSelector_atLeastOnePropertyExists_returnsFalse() {
        final String separator = System.getProperty("line.separator");
        String vCard = "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator
                + "TEL:0123456789" + separator;

        byte[] organizationSelector = new byte[] {0x01, 0x00, 0x00};
        PropertySelector selector = new PropertySelector(organizationSelector);

        assertThat(selector.checkVCardSelector(vCard, "0")).isFalse();
    }

    @Test
    public void PropertySelector_checkVCardSelector_allPropertiesExist_returnsTrue() {
        final String separator = System.getProperty("line.separator");
        String vCard = "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator
                + "TEL:0123456789" + separator;

        byte[] fullNameAndEmailSelector = new byte[] {0x01, 0x02};
        PropertySelector selector = new PropertySelector(fullNameAndEmailSelector);

        assertThat(selector.checkVCardSelector(vCard, "1")).isTrue();
    }

    @Test
    public void PropertySelector_checkVCardSelector_allPropertiesExist_returnsFalse() {
        final String separator = System.getProperty("line.separator");
        String vCard = "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator
                + "TEL:0123456789" + separator;

        byte[] fullNameAndOrganizationSelector = new byte[] {0x01, 0x00, 0x02};
        PropertySelector selector = new PropertySelector(fullNameAndOrganizationSelector);

        assertThat(selector.checkVCardSelector(vCard, "1")).isFalse();
    }

    @Test
    public void ContactCursorFilter_filterByOffset() {
        Cursor contactCursor = mock(Cursor.class);
        int contactIdColumn = 5;
        when(contactCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
                .thenReturn(contactIdColumn);

        long[] contactIds = new long[] {1001, 1001, 1002, 1002, 1003, 1003, 1004};
        AtomicInteger currentPos = new AtomicInteger(-1);
        when(contactCursor.moveToNext()).thenAnswer(invocation -> {
            if (currentPos.get() < contactIds.length - 1) {
                currentPos.incrementAndGet();
                return true;
            }
            return false;
        });
        when(contactCursor.getLong(contactIdColumn))
                .thenAnswer(invocation -> contactIds[currentPos.get()]);

        int offset = 3;
        Cursor resultCursor = ContactCursorFilter.filterByOffset(contactCursor, offset);

        // Should return cursor containing [1003]
        assertThat(resultCursor.getCount()).isEqualTo(1);
        assertThat(getContactsIdFromCursor(resultCursor, 0)).isEqualTo(1003);
    }

    @Test
    public void ContactCursorFilter_filterByRange() {
        Cursor contactCursor = mock(Cursor.class);
        int contactIdColumn = 5;
        when(contactCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
                .thenReturn(contactIdColumn);

        long[] contactIds = new long[] {1001, 1001, 1002, 1002, 1003, 1003, 1004};
        AtomicInteger currentPos = new AtomicInteger(-1);
        when(contactCursor.moveToNext()).thenAnswer(invocation -> {
            if (currentPos.get() < contactIds.length - 1) {
                currentPos.incrementAndGet();
                return true;
            }
            return false;
        });
        when(contactCursor.getLong(contactIdColumn))
                .thenAnswer(invocation -> contactIds[currentPos.get()]);

        int startPoint = 2;
        int endPoint = 4;
        Cursor resultCursor = ContactCursorFilter.filterByRange(
                contactCursor, startPoint, endPoint);

        // Should return cursor containing [1002, 1003, 1004]
        assertThat(resultCursor.getCount()).isEqualTo(3);
        assertThat(getContactsIdFromCursor(resultCursor, 0)).isEqualTo(1002);
        assertThat(getContactsIdFromCursor(resultCursor, 1)).isEqualTo(1003);
        assertThat(getContactsIdFromCursor(resultCursor, 2)).isEqualTo(1004);
    }

    private long getContactsIdFromCursor(Cursor cursor, int position) {
        int index = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
        cursor.moveToPosition(position);
        return cursor.getLong(index);
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -333,4 +333,14 @@ public class BluetoothPbapVcardManagerTest {

        assertThat(mManager.stripTelephoneNumber(vCard)).isEqualTo(expectedResult);
    }

    @Test
    public void getNameFromVCard() {
        final String separator = System.getProperty("line.separator");
        String vCard = "N:Test Name" + separator
                + "FN:Test Full Name" + separator
                + "EMAIL:android@android.com:" + separator;

        assertThat(BluetoothPbapVcardManager.getNameFromVCard(vCard)).isEqualTo("Test Name");
    }
}