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

Commit e0c6c099 authored by Steve Kondik's avatar Steve Kondik
Browse files

Merge branch 'jb_mr2' of git://codeaurora.org/platform/packages/apps/Bluetooth into cm-10.2

parents 0a0864e9 3e0960de
Loading
Loading
Loading
Loading
+107 −31
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2008-2009, Motorola, Inc.
 *
 * All rights reserved.
@@ -73,18 +74,11 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
            0x08, 0x00, 0x20, 0x0c, (byte)0x9a, 0x66
    };

    // Currently not support SIM card
    // Note: SIM also supported in this version
    private static final String[] LEGAL_PATH = {
            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
            "/telecom/cch"
    };

    @SuppressWarnings("unused")
    private static final String[] LEGAL_PATH_WITH_SIM = {
            "/telecom", "/telecom/pb", "/telecom/ich", "/telecom/och", "/telecom/mch",
            "/telecom/cch","/SIM1","/SIM1/telecom", "/SIM1/telecom/ich", "/SIM1/telecom/och",
            "/SIM1/telecom/mch", "/SIM1/telecom/cch", "/SIM1/telecom/pb"

    };

    // SIM card
@@ -115,6 +109,17 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {

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

    private static final String SIM_PATH = "/SIM1/telecom";

    private static final String SIM_ICH_PATH = "/SIM1/telecom/ich";

    private static final String SIM_OCH_PATH = "/SIM1/telecom/och";

    private static final String SIM_MCH_PATH = "/SIM1/telecom/mch";

    private static final String SIM_CCH_PATH = "/SIM1/telecom/cch";

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

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

        public static final int COMBINED_CALL_HISTORY = 5;

        public static final int SIM_PHONEBOOK = 6;
    }

    public BluetoothPbapObexServer(Handler callback, Context context) {
@@ -350,31 +357,35 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {

            if (mCurrentPath.equals(PB_PATH)) {
                appParamValue.needTag = ContentType.PHONEBOOK;
            } else if (mCurrentPath.equals(ICH_PATH)) {
            } else if (mCurrentPath.equals(ICH_PATH) || mCurrentPath.equals(SIM_ICH_PATH)) {
                appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
            } else if (mCurrentPath.equals(OCH_PATH)) {
            } else if (mCurrentPath.equals(OCH_PATH) || mCurrentPath.equals(SIM_OCH_PATH)) {
                appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
            } else if (mCurrentPath.equals(MCH_PATH)) {
            } else if (mCurrentPath.equals(MCH_PATH) || mCurrentPath.equals(SIM_MCH_PATH)) {
                appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
                mNeedNewMissedCallsNum = true;
            } else if (mCurrentPath.equals(CCH_PATH)) {
            } else if (mCurrentPath.equals(CCH_PATH) || mCurrentPath.equals(SIM_CCH_PATH)) {
                appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
            } else if (mCurrentPath.equals(SIM_PB_PATH)) {
                appParamValue.needTag = ContentType.SIM_PHONEBOOK;
            } else {
                Log.w(TAG, "mCurrentpath is not valid path!!!");
                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
            }
            if (D) Log.v(TAG, "onGet(): appParamValue.needTag=" + appParamValue.needTag);
        } else {
            // Not support SIM card currently
            if (name.contains(SIM1.subSequence(0, SIM1.length()))) {
                Log.w(TAG, "Not support access SIM card info!");
                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
            }

            // we have weak name checking here to provide better
            // compatibility with other devices,although unique name such as
            // "pb.vcf" is required by SIG spec.
            if (name.contains(PB.subSequence(0, PB.length()))) {
            if (((name.contains(PB.subSequence(0, PB.length())) &&
                 name.contains(SIM1.subSequence(0, SIM1.length()))) &&
                (type.equals(TYPE_PB))) ||
                (((name.contains(PB.subSequence(0, PB.length()))) &&
                (mCurrentPath.equals(SIM_PATH))) && (type.equals(TYPE_LISTING))))
            {
                appParamValue.needTag = ContentType.SIM_PHONEBOOK;
                if (D) Log.v(TAG, "download SIM phonebook request");
            } else if (name.contains(PB.subSequence(0, PB.length()))) {
                appParamValue.needTag = ContentType.PHONEBOOK;
                if (D) Log.v(TAG, "download phonebook request");
            } else if (name.contains(ICH.subSequence(0, ICH.length()))) {
@@ -451,6 +462,10 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {

        public boolean vcard21;

        public byte[] filter;

        public boolean ignorefilter;

        public AppParamValue() {
            maxListCount = 0xFFFF;
            listStartOffset = 0;
@@ -459,6 +474,9 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
            order = "";
            needTag = 0x00;
            vcard21 = true;
            //Filter is not set by default
            ignorefilter = true;
            filter = new byte[] {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} ;
        }

        public void dump() {
@@ -473,10 +491,17 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
            AppParamValue appParamValue) {
        int i = 0;
        boolean parseOk = true;
        while (i < appParam.length) {
        while ((i < appParam.length) && (parseOk == true)) {
            switch (appParam[i]) {
                case ApplicationParameter.TRIPLET_TAGID.FILTER_TAGID:
                    i += 2; // length and tag field in triplet
                    for (int index=0; index < ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH;
                         index++) {
                        if (appParam[i+index] != 0){
                            appParamValue.ignorefilter = false;
                            appParamValue.filter[index] = appParam[i+index];
                        }
                    }
                    i += ApplicationParameter.TRIPLET_LENGTH.FILTER_LENGTH;
                    break;
                case ApplicationParameter.TRIPLET_TAGID.ORDER_TAGID:
@@ -548,6 +573,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
            String searchAttr) {
        StringBuilder result = new StringBuilder();
        int itemsFound = 0;
        boolean SIM = false;
        result.append("<?xml version=\"1.0\"?>");
        result.append("<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">");
        result.append("<vCard-listing version=\"1.0\">");
@@ -556,10 +582,23 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        if (type == ContentType.PHONEBOOK) {
            if (searchAttr.equals("0")) { // search by name
                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
                        "name");
                        "name", SIM);
            } else if (searchAttr.equals("1")) { // search by number
                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
                        "number", SIM);
            }// end of search by number
            else {
                return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
            }
        }// SIM Phonebook listing Request
        else if (type == ContentType.SIM_PHONEBOOK) {
            SIM = true;
            if (searchAttr.equals("0")) { // search by name
                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
                        "name", SIM);
            } else if (searchAttr.equals("1")) { // search by number
                itemsFound = createList(maxListCount, listStartOffset, searchValue, result,
                        "number");
                        "number", SIM);
            }// end of search by number
            else {
                return ResponseCodes.OBEX_HTTP_PRECON_FAILED;
@@ -588,9 +627,15 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
    }

    private int createList(final int maxListCount, final int listStartOffset,
            final String searchValue, StringBuilder result, String type) {
        final String searchValue, StringBuilder result, String type, boolean SIM) {
        int itemsFound = 0;
        ArrayList<String> nameList = mVcardManager.getPhonebookNameList(mOrderBy);
        ArrayList<String> nameList = null;
        //check if current request is for SIM
        if(SIM) {
             nameList = mVcardManager.getSIMPhonebookNameList(mOrderBy);
        }else{
             nameList = mVcardManager.getPhonebookNameList(mOrderBy);
        }
        final int requestSize = nameList.size() >= maxListCount ? maxListCount : nameList.size();
        final int listSize = nameList.size();
        String compareValue = "", currentValue;
@@ -599,8 +644,13 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                    + listStartOffset + " searchValue=" + searchValue);

        if (type.equals("number")) {
            ArrayList<String> names = null;
            // query the number, to get the names
            ArrayList<String> names = mVcardManager.getContactNamesByNumber(searchValue);
            if(SIM) {
                names = mVcardManager.getSIMContactNamesByNumber(searchValue);
            } else{
                  names = mVcardManager.getContactNamesByNumber(searchValue);
            }
            for (int i = 0; i < names.size(); i++) {
                compareValue = names.get(i).trim();
                if (D) Log.d(TAG, "compareValue=" + compareValue);
@@ -850,6 +900,18 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                return pushBytes(op, ownerVcard);
            } else {
                return mVcardManager.composeAndSendPhonebookOneVcard(op, intIndex, vcard21, null,
                        mOrderBy, appParamValue.ignorefilter, appParamValue.filter);
            }
       } else if (appParamValue.needTag == ContentType.SIM_PHONEBOOK) {
            if (intIndex < 0 || intIndex >= size) {
                Log.w(TAG, "The requested vcard is not acceptable! name= " + name);
                return ResponseCodes.OBEX_HTTP_OK;
            } else if (intIndex == 0) {
                // For PB_PATH, 0.vcf is the phone number of this phone.
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21, null);
                return pushBytes(op, ownerVcard);
            } else {
                return mVcardManager.composeAndSendSIMPhonebookOneVcard(op, intIndex, vcard21, null,
                        mOrderBy );
            }
        } else {
@@ -861,7 +923,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
            // begin from 1.vcf
            if (intIndex >= 1) {
                return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
                        intIndex, intIndex, vcard21);
                        intIndex, intIndex, vcard21, appParamValue.ignorefilter, appParamValue.filter);
            }
        }
        return ResponseCodes.OBEX_HTTP_OK;
@@ -901,7 +963,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        }

        // 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.SIM_PHONEBOOK)) {
            if (requestSize > CALLLOG_NUM_LIMIT) {
               requestSize = CALLLOG_NUM_LIMIT;
            }
@@ -922,15 +985,28 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                    return pushBytes(op, ownerVcard);
                } else {
                    return mVcardManager.composeAndSendPhonebookVcards(op, 1, endPoint, vcard21,
                            ownerVcard);
                            ownerVcard, appParamValue.ignorefilter, appParamValue.filter);
                }
            } else {
                return mVcardManager.composeAndSendPhonebookVcards(op, startPoint, endPoint,
                        vcard21, null, appParamValue.ignorefilter, appParamValue.filter);
            }
        } else if (appParamValue.needTag == BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK) {
            if (startPoint == 0) {
                String ownerVcard = mVcardManager.getOwnerPhoneNumberVcard(vcard21, null);
                if (endPoint == 0) {
                    return pushBytes(op, ownerVcard);
                } else {
                    return mVcardManager.composeAndSendSIMPhonebookVcards(op, 1, endPoint, vcard21,
                            ownerVcard);
                }
            } else {
                return mVcardManager.composeAndSendSIMPhonebookVcards(op, startPoint, endPoint,
                        vcard21, null);
            }
        } else {
            return mVcardManager.composeAndSendCallLogVcards(appParamValue.needTag, op,
                    startPoint + 1, endPoint + 1, vcard21);
                    startPoint + 1, endPoint + 1, vcard21, appParamValue.ignorefilter, appParamValue.filter);
        }
    }

+241 −0
Original line number Diff line number Diff line
/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
 * Copyright (C) 2010 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 com.android.bluetooth.R;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import com.android.vcard.VCardBuilder;
import com.android.vcard.VCardConfig;
import com.android.vcard.VCardConstants;
import com.android.vcard.VCardUtils;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Collections;
import java.util.Comparator;

/**
 * VCard composer especially for Call Log used in Bluetooth.
 */
public class BluetoothPbapSIMvCardComposer {
    private static final String TAG = "SIMvCardComposer";

    private static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
        "Failed to get database information";

    private static final String FAILURE_REASON_NO_ENTRY =
        "There's no exportable in the database";

    private static final String FAILURE_REASON_NOT_INITIALIZED =
        "The vCard composer object is not correctly initialized";

    /** Should be visible only from developers... (no need to translate, hopefully) */
    private static final String FAILURE_REASON_UNSUPPORTED_URI =
        "The Uri vCard composer received is not supported by the composer.";

    private static final String NO_ERROR = "No error";

    private final String SIM_URI = "content://icc/adn";

    private static final String[] SIM_PROJECTION = new String[] {
                Contacts.DISPLAY_NAME,
                CommonDataKinds.Phone.NUMBER,
                CommonDataKinds.Phone.TYPE,
                CommonDataKinds.Phone.LABEL};

    private static final int NAME_COLUMN_INDEX = 0;
    private static final int NUMBER_COLUMN_INDEX = 1;
    private static final int NUMBERTYPE_COLUMN_INDEX = 2;
    private static final int NUMBERLABEL_COLUMN_INDEX = 3;


    private final Context mContext;
    private ContentResolver mContentResolver;
    private Cursor mCursor;
    private boolean mTerminateIsCalled;
    private String mErrorReason = NO_ERROR;
    public BluetoothPbapSIMvCardComposer(final Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
    }

    public boolean init(final Uri contentUri, final String selection,
            final String[] selectionArgs, final String sortOrder) {
            final Uri myUri = Uri.parse(SIM_URI);
        if (!myUri.equals(contentUri)) {

            mErrorReason = FAILURE_REASON_UNSUPPORTED_URI;
            return false;
        }

        mCursor = mContentResolver.query(
                contentUri, SIM_PROJECTION, null, null,sortOrder); //checkpoint Figure out if we can apply selection, projection and sort order.

        if (mCursor == null) {
            mErrorReason = FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO;
            return false;
        }
        if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) {
            try {
                mCursor.close();
            } catch (SQLiteException e) {
                Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
            } finally {
                mErrorReason = FAILURE_REASON_NO_ENTRY;
                mCursor = null;
            }
            return false;
        }

        return true;
    }


    public String createOneEntry(boolean vcardVer21) {
        if (mCursor == null || mCursor.isAfterLast()) {
            mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
            return null;
        }
        try {
            return createOnevCardEntryInternal(vcardVer21);
        } finally {
            mCursor.moveToNext();
        }
    }

    private String createOnevCardEntryInternal(boolean vcardVer21) {
        final int vcardType = (vcardVer21 ? VCardConfig.VCARD_TYPE_V21_GENERIC :
                VCardConfig.VCARD_TYPE_V30_GENERIC) |
                VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING;
        final VCardBuilder builder = new VCardBuilder(vcardType);
        String name = mCursor.getString(NAME_COLUMN_INDEX);
        if (TextUtils.isEmpty(name)) {
            name = mCursor.getString(NUMBER_COLUMN_INDEX);
        }
        final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
        builder.appendLine(VCardConstants.PROPERTY_FN, name, needCharset, false);
        builder.appendLine(VCardConstants.PROPERTY_N, name, needCharset, false);

        String number = mCursor.getString(NUMBER_COLUMN_INDEX);
        if (number.equals("-1")) {
            number = mContext.getString(R.string.unknownNumber);
        }

        // checkpoint Figure out what are the type and label
        final int type = mCursor.getInt(NUMBERTYPE_COLUMN_INDEX);
        String label = mCursor.getString(NUMBERLABEL_COLUMN_INDEX);
        if (TextUtils.isEmpty(label)) {
            label = Integer.toString(type);
        }
        builder.appendTelLine(type, label, number, false);
        return builder.toString();
    }

    public void terminate() {
        if (mCursor != null) {
            try {
                mCursor.close();
            } catch (SQLiteException e) {
                Log.e(TAG, "SQLiteException on Cursor#close(): " + e.getMessage());
            }
            mCursor = null;
        }

        mTerminateIsCalled = true;
    }

    @Override
    public void finalize() {
        if (!mTerminateIsCalled) {
            terminate();
        }
    }

    public int getCount() {
        if (mCursor == null) {
            return 0;
        }
        return mCursor.getCount();
    }

    public boolean isAfterLast() {
        if (mCursor == null) {
            return false;
        }
        return mCursor.isAfterLast();
    }

    public void moveToPosition(final int position, boolean sortalpha){
        if(mCursor == null) {
            return;
        }
        if(sortalpha) {
            setpositionbyalpha(position);
            return;
        }
        mCursor.moveToPosition(position);
    }

    public String getErrorReason() {
        return mErrorReason;
    }

    public void setpositionbyalpha(int position){
        if(mCursor == null) {
            return;
        }
        ArrayList<String> nameList = new ArrayList<String>();
        for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor
                        .moveToNext()) {
            String name = mCursor.getString(NAME_COLUMN_INDEX);
            if (TextUtils.isEmpty(name)) {
                name = mContext.getString(android.R.string.unknownName);
            }
            nameList.add(name);
        }

        Collections.sort(nameList, new Comparator <String> ()
                                 {@Override
                                  public int compare(String str1, String str2){
                                      return str1.compareToIgnoreCase(str2);
                                 }
        });

        for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor
                        .moveToNext()) {
            if(mCursor.getString(NAME_COLUMN_INDEX).equals(nameList.get(position))) {
              break;
            }

        }
    }

}

+533 −10

File changed.

Preview size limit exceeded, changes collapsed.