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

Commit 60596bec authored by Andrew Cheng's avatar Andrew Cheng Committed by Gerrit Code Review
Browse files

Merge "PBAP server, send favorite contacts"

parents f995d62a 131e7782
Loading
Loading
Loading
Loading
+51 −14
Original line number Original line Diff line number Diff line
@@ -97,6 +97,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
    private static final String[] LEGAL_PATH = {
    private static final String[] LEGAL_PATH = {
            "/telecom",
            "/telecom",
            "/telecom/pb",
            "/telecom/pb",
            "/telecom/fav",
            "/telecom/ich",
            "/telecom/ich",
            "/telecom/och",
            "/telecom/och",
            "/telecom/mch",
            "/telecom/mch",
@@ -106,6 +107,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
    @SuppressWarnings("unused") private static final String[] LEGAL_PATH_WITH_SIM = {
    @SuppressWarnings("unused") private static final String[] LEGAL_PATH_WITH_SIM = {
            "/telecom",
            "/telecom",
            "/telecom/pb",
            "/telecom/pb",
            "/telecom/fav",
            "/telecom/ich",
            "/telecom/ich",
            "/telecom/och",
            "/telecom/och",
            "/telecom/mch",
            "/telecom/mch",
@@ -138,6 +140,9 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
    // phone book
    // phone book
    private static final String PB = "pb";
    private static final String PB = "pb";


    // favorites
    private static final String FAV = "fav";

    private static final String TELECOM_PATH = "/telecom";
    private static final String TELECOM_PATH = "/telecom";


    private static final String ICH_PATH = "/telecom/ich";
    private static final String ICH_PATH = "/telecom/ich";
@@ -150,6 +155,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {


    private static final String PB_PATH = "/telecom/pb";
    private static final String PB_PATH = "/telecom/pb";


    private static final String FAV_PATH = "/telecom/fav";

    // type for list vcard objects
    // type for list vcard objects
    private static final String TYPE_LISTING = "x-bt/vcard-listing";
    private static final String TYPE_LISTING = "x-bt/vcard-listing";


@@ -212,6 +219,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        public static final int MISSED_CALL_HISTORY = 4;
        public static final int MISSED_CALL_HISTORY = 4;


        public static final int COMBINED_CALL_HISTORY = 5;
        public static final int COMBINED_CALL_HISTORY = 5;

        public static final int FAVORITES = 6;
    }
    }


    public BluetoothPbapObexServer(Handler callback, Context context,
    public BluetoothPbapObexServer(Handler callback, Context context,
@@ -441,6 +450,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {


            if (mCurrentPath.equals(PB_PATH)) {
            if (mCurrentPath.equals(PB_PATH)) {
                appParamValue.needTag = ContentType.PHONEBOOK;
                appParamValue.needTag = ContentType.PHONEBOOK;
            } else if (mCurrentPath.equals(FAV_PATH)) {
                appParamValue.needTag = ContentType.FAVORITES;
            } else if (mCurrentPath.equals(ICH_PATH)) {
            } else if (mCurrentPath.equals(ICH_PATH)) {
                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
            } else if (mCurrentPath.equals(OCH_PATH)) {
            } else if (mCurrentPath.equals(OCH_PATH)) {
@@ -478,6 +489,11 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                if (D) {
                if (D) {
                    Log.v(TAG, "download phonebook request");
                    Log.v(TAG, "download phonebook request");
                }
                }
            } else if (isNameMatchTarget(name, FAV)) {
                appParamValue.needTag = ContentType.FAVORITES;
                if (D) {
                    Log.v(TAG, "download favorites request");
                }
            } else if (isNameMatchTarget(name, ICH)) {
            } else if (isNameMatchTarget(name, ICH)) {
                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
                appParamValue.callHistoryVersionCounter =
                appParamValue.callHistoryVersionCounter =
@@ -751,7 +767,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        result.append("<vCard-listing version=\"1.0\">");
        result.append("<vCard-listing version=\"1.0\">");


        // Phonebook listing request
        // Phonebook listing request
        if (appParamValue.needTag == ContentType.PHONEBOOK) {
        if ((appParamValue.needTag == ContentType.PHONEBOOK)
                || (appParamValue.needTag == ContentType.FAVORITES)) {
            String type = "";
            String type = "";
            if (appParamValue.searchAttr.equals("0")) {
            if (appParamValue.searchAttr.equals("0")) {
                type = "name";
                type = "name";
@@ -948,7 +965,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                    checkPbapFeatureSupport(mFolderVersionCounterbitMask);
                    checkPbapFeatureSupport(mFolderVersionCounterbitMask);
        }
        }
        boolean needSendPhonebookVersionCounters = false;
        boolean needSendPhonebookVersionCounters = false;
        if (isNameMatchTarget(name, PB)) {
        if (isNameMatchTarget(name, PB) || isNameMatchTarget(name, FAV)) {
            needSendPhonebookVersionCounters =
            needSendPhonebookVersionCounters =
                    checkPbapFeatureSupport(mFolderVersionCounterbitMask);
                    checkPbapFeatureSupport(mFolderVersionCounterbitMask);
        }
        }
@@ -1194,11 +1211,12 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        if (appParamValue.needTag == 0) {
        if (appParamValue.needTag == 0) {
            Log.w(TAG, "wrong path!");
            Log.w(TAG, "wrong path!");
            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
            return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
        } else if (appParamValue.needTag == ContentType.PHONEBOOK) {
        } else if ((appParamValue.needTag == ContentType.PHONEBOOK)
                || (appParamValue.needTag == ContentType.FAVORITES)) {
            if (intIndex < 0 || intIndex >= size) {
            if (intIndex < 0 || intIndex >= size) {
                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
                return ResponseCodes.OBEX_HTTP_NOT_FOUND;
            } else if (intIndex == 0) {
            } else if ((intIndex == 0) && (appParamValue.needTag == ContentType.PHONEBOOK)) {
                // For PB_PATH, 0.vcf is the phone number of this phone.
                // For PB_PATH, 0.vcf is the phone number of this phone.
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
                        appParamValue.ignorefilter ? null : appParamValue.propertySelector);
                        appParamValue.ignorefilter ? null : appParamValue.propertySelector);
@@ -1254,30 +1272,49 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {


        int requestSize =
        int requestSize =
                pbSize >= appParamValue.maxListCount ? appParamValue.maxListCount : pbSize;
                pbSize >= appParamValue.maxListCount ? appParamValue.maxListCount : pbSize;
        int startPoint = appParamValue.listStartOffset;
        /**
        if (startPoint < 0 || startPoint >= pbSize) {
         * startIndex (resp., lastIndex) corresponds to the index of the first (resp., last)
         * vcard entry in the phonebook object.
         * PBAP v1.2.3: only pb starts indexing at 0.vcf (owner card), the other phonebook
         * objects (e.g., fav) start at 1.vcf. Additionally, the owner card is included in
         * pb's pbSize. This means pbSize corresponds to the index of the last vcf in the fav
         * phonebook object, but does not for the pb phonebook object.
         */
        int startIndex = 1;
        int lastIndex = pbSize;
        if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.PHONEBOOK) {
            startIndex = 0;
            lastIndex = pbSize - 1;
        }
        // [startPoint, endPoint] denote the range of vcf indices to send, inclusive.
        int startPoint = startIndex + appParamValue.listStartOffset;
        int endPoint = startPoint + requestSize - 1;
        if (appParamValue.listStartOffset < 0 || startPoint > lastIndex) {
            Log.w(TAG, "listStartOffset is not correct! " + startPoint);
            Log.w(TAG, "listStartOffset is not correct! " + startPoint);
            return ResponseCodes.OBEX_HTTP_OK;
            return ResponseCodes.OBEX_HTTP_OK;
        }
        }
        if (endPoint > lastIndex) {
            endPoint = lastIndex;
        }


        // Limit the number of call log to CALLLOG_NUM_LIMIT
        // Limit the number of call log to CALLLOG_NUM_LIMIT
        if (appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) {
        if ((appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK)
                && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES)) {
            if (requestSize > CALLLOG_NUM_LIMIT) {
            if (requestSize > CALLLOG_NUM_LIMIT) {
                requestSize = CALLLOG_NUM_LIMIT;
                requestSize = CALLLOG_NUM_LIMIT;
            }
            }
        }
        }


        int endPoint = startPoint + requestSize - 1;
        if (endPoint > pbSize - 1) {
            endPoint = pbSize - 1;
        }
        if (D) {
        if (D) {
            Log.d(TAG, "pullPhonebook(): requestSize=" + requestSize + " startPoint=" + startPoint
            Log.d(TAG, "pullPhonebook(): requestSize=" + requestSize + " startPoint=" + startPoint
                    + " endPoint=" + endPoint);
                    + " endPoint=" + endPoint);
        }
        }


        boolean vcard21 = appParamValue.vcard21;
        boolean vcard21 = appParamValue.vcard21;
        if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.PHONEBOOK) {
        boolean favorites =
                (appParamValue.needTag == BluetoothPbapObexServer.ContentType.FAVORITES);
        if ((appParamValue.needTag == BluetoothPbapObexServer.ContentType.PHONEBOOK)
                || favorites) {
            if (startPoint == 0) {
            if (startPoint == 0) {
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21,
                        appParamValue.ignorefilter ? null : appParamValue.propertySelector);
                        appParamValue.ignorefilter ? null : appParamValue.propertySelector);
@@ -1287,13 +1324,13 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                    return mVcardManager.composeAndSendPhonebookVcards(op, 1, endPoint, vcard21,
                    return mVcardManager.composeAndSendPhonebookVcards(op, 1, endPoint, vcard21,
                            ownerVcard, needSendBody, pbSize, appParamValue.ignorefilter,
                            ownerVcard, needSendBody, pbSize, appParamValue.ignorefilter,
                            appParamValue.propertySelector, appParamValue.vCardSelector,
                            appParamValue.propertySelector, appParamValue.vCardSelector,
                            appParamValue.vCardSelectorOperator, mVcardSelector);
                            appParamValue.vCardSelectorOperator, mVcardSelector, favorites);
                }
                }
            } else {
            } else {
                return mVcardManager.composeAndSendPhonebookVcards(op, startPoint, endPoint,
                return mVcardManager.composeAndSendPhonebookVcards(op, startPoint, endPoint,
                        vcard21, null, needSendBody, pbSize, appParamValue.ignorefilter,
                        vcard21, null, needSendBody, pbSize, appParamValue.ignorefilter,
                        appParamValue.propertySelector, appParamValue.vCardSelector,
                        appParamValue.propertySelector, appParamValue.vCardSelector,
                        appParamValue.vCardSelectorOperator, mVcardSelector);
                        appParamValue.vCardSelectorOperator, mVcardSelector, favorites);
            }
            }
        } else {
        } else {
            return mVcardManager.composeAndSendSelectedCallLogVcards(appParamValue.needTag, op,
            return mVcardManager.composeAndSendSelectedCallLogVcards(appParamValue.needTag, op,
+2 −1
Original line number Original line Diff line number Diff line
@@ -139,7 +139,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
    private ObexServerSockets mServerSockets = null;
    private ObexServerSockets mServerSockets = null;


    private static final int SDP_PBAP_SERVER_VERSION = 0x0102;
    private static final int SDP_PBAP_SERVER_VERSION = 0x0102;
    private static final int SDP_PBAP_SUPPORTED_REPOSITORIES = 0x0001;
    // PBAP v1.2.3, Sec. 7.1.2: local phonebook and favorites
    private static final int SDP_PBAP_SUPPORTED_REPOSITORIES = 0x0009;
    private static final int SDP_PBAP_SUPPORTED_FEATURES = 0x021F;
    private static final int SDP_PBAP_SUPPORTED_FEATURES = 0x021F;


    /* PBAP will use Bluetooth notification ID from 1000000 (included) to 2000000 (excluded).
    /* PBAP will use Bluetooth notification ID from 1000000 (included) to 2000000 (excluded).
+29 −8
Original line number Original line Diff line number Diff line
@@ -153,7 +153,8 @@ public class BluetoothPbapVcardManager {
        int size;
        int size;
        switch (type) {
        switch (type) {
            case BluetoothPbapObexServer.ContentType.PHONEBOOK:
            case BluetoothPbapObexServer.ContentType.PHONEBOOK:
                size = getContactsSize();
            case BluetoothPbapObexServer.ContentType.FAVORITES:
                size = getContactsSize(type);
                break;
                break;
            default:
            default:
                size = getCallHistorySize(type);
                size = getCallHistorySize(type);
@@ -165,16 +166,30 @@ public class BluetoothPbapVcardManager {
        return size;
        return size;
    }
    }


    public final int getContactsSize() {
    /**
     * Returns the number of contacts (i.e., vcf) in a phonebook object.
     * @param type specifies which phonebook object, e.g., pb, fav
     * @return
     */
    public final int getContactsSize(final int type) {
        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
        final Uri myUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext);
        Cursor contactCursor = null;
        Cursor contactCursor = null;
        String selectionClause = null;
        if (type == BluetoothPbapObexServer.ContentType.FAVORITES) {
            selectionClause = Phone.STARRED + " = 1";
        }
        try {
        try {
            contactCursor = mResolver.query(myUri, new String[]{Phone.CONTACT_ID}, null, null,
            contactCursor = mResolver.query(myUri,
                    Phone.CONTACT_ID);
                    new String[]{Phone.CONTACT_ID}, selectionClause,
                    null, Phone.CONTACT_ID);
            if (contactCursor == null) {
            if (contactCursor == null) {
                return 0;
                return 0;
            }
            }
            return getDistinctContactIdSize(contactCursor) + 1; // always has the 0.vcf
            int contactsSize = getDistinctContactIdSize(contactCursor);
            if (type == BluetoothPbapObexServer.ContentType.PHONEBOOK) {
                contactsSize += 1; // pb has the 0.vcf owner's card
            }
            return contactsSize;
        } catch (CursorWindowAllocationException e) {
        } catch (CursorWindowAllocationException e) {
            Log.e(TAG, "CursorWindowAllocationException while getting Contacts size");
            Log.e(TAG, "CursorWindowAllocationException while getting Contacts size");
        } finally {
        } finally {
@@ -551,7 +566,7 @@ public class BluetoothPbapVcardManager {
    final int composeAndSendPhonebookVcards(Operation op, final int startPoint, final int endPoint,
    final int composeAndSendPhonebookVcards(Operation op, final int startPoint, final int endPoint,
            final boolean vcardType21, String ownerVCard, int needSendBody, int pbSize,
            final boolean vcardType21, String ownerVCard, int needSendBody, int pbSize,
            boolean ignorefilter, byte[] filter, byte[] vcardselector, String vcardselectorop,
            boolean ignorefilter, byte[] filter, byte[] vcardselector, String vcardselectorop,
            boolean vcardselect) {
            boolean vcardselect, boolean favorites) {
        if (startPoint < 1 || startPoint > endPoint) {
        if (startPoint < 1 || startPoint > endPoint) {
            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
@@ -562,9 +577,15 @@ public class BluetoothPbapVcardManager {
        Cursor contactIdCursor = new MatrixCursor(new String[]{
        Cursor contactIdCursor = new MatrixCursor(new String[]{
                Phone.CONTACT_ID
                Phone.CONTACT_ID
        });
        });

        String selectionClause = null;
        if (favorites) {
            selectionClause = Phone.STARRED + " = 1";
        }

        try {
        try {
            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, null, null,
            contactCursor = mResolver.query(myUri, PHONES_CONTACTS_PROJECTION, selectionClause,
                    Phone.CONTACT_ID);
                    null, Phone.CONTACT_ID);
            if (contactCursor != null) {
            if (contactCursor != null) {
                contactIdCursor =
                contactIdCursor =
                        ContactCursorFilter.filterByRange(contactCursor, startPoint, endPoint);
                        ContactCursorFilter.filterByRange(contactCursor, startPoint, endPoint);