public void handleCpbsCommand(String atString, int type) { // Select PhoneBook memory Storage log("handleCpbsCommand - atString = " + atString); int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; int atCommandErrorCode = -1; String atCommandResponse = null; switch (type) { case TYPE_READ: // Read log("handleCpbsCommand - read command"); // Return current size and max size if ("SM".equals(mCurrentPhonebook)) { atCommandResponse = "+CPBS: \"SM\",0," + getMaxPhoneBookSize(0); atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; break; } PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); if (pbr == null) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; break; } int size = pbr.cursor.getCount(); atCommandResponse = "+CPBS: \"" + mCurrentPhonebook + "\"," + size + "," + getMaxPhoneBookSize(size); pbr.cursor.close(); pbr.cursor = null; atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; break; case TYPE_TEST: // Test log("handleCpbsCommand - test command"); atCommandResponse = ("+CPBS: (\"ME\",\"SM\",\"DC\",\"RC\",\"MC\")"); atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; break; case TYPE_SET: // Set log("handleCpbsCommand - set command"); String[] args = atString.split("="); // Select phonebook memory if (args.length < 2 || !(args[1] instanceof String)) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; break; } String pb = ((String) args[1]).trim(); while (pb.endsWith("\"")) pb = pb.substring(0, pb.length() - 1); while (pb.startsWith("\"")) pb = pb.substring(1, pb.length()); if (getPhonebookResult(pb, false) == null && !"SM".equals(pb)) { if (DBG) log("Dont know phonebook: '" + pb + "'"); atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; break; } mCurrentPhonebook = pb; atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; break; case TYPE_UNKNOWN: default: log("handleCpbsCommand - invalid chars"); atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; } if (atCommandResponse != null) mStateMachine.atResponseStringNative(atCommandResponse); mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode); }
private synchronized boolean queryPhonebook(String pb, PhonebookResult pbr) { String where; boolean ancillaryPhonebook = true; if (pb.equals("ME")) { ancillaryPhonebook = false; where = VISIBLE_PHONEBOOK_WHERE; } else if (pb.equals("DC")) { where = OUTGOING_CALL_WHERE; } else if (pb.equals("RC")) { where = INCOMING_CALL_WHERE; } else if (pb.equals("MC")) { where = MISSED_CALL_WHERE; } else { return false; } if (pbr.cursor != null) { pbr.cursor.close(); pbr.cursor = null; } if (ancillaryPhonebook) { pbr.cursor = mContext .getContentResolver() .query( Calls.CONTENT_URI, CALLS_PROJECTION, where, null, Calls.DEFAULT_SORT_ORDER + " LIMIT " + MAX_PHONEBOOK_SIZE); if (pbr.cursor == null) return false; pbr.numberColumn = pbr.cursor.getColumnIndexOrThrow(Calls.NUMBER); pbr.typeColumn = -1; pbr.nameColumn = -1; } else { pbr.cursor = mContext .getContentResolver() .query( Phone.CONTENT_URI, PHONES_PROJECTION, where, null, Phone.NUMBER + " LIMIT " + MAX_PHONEBOOK_SIZE); if (pbr.cursor == null) return false; pbr.numberColumn = pbr.cursor.getColumnIndex(Phone.NUMBER); pbr.typeColumn = pbr.cursor.getColumnIndex(Phone.TYPE); pbr.nameColumn = pbr.cursor.getColumnIndex(Phone.DISPLAY_NAME); } Log.i(TAG, "Refreshed phonebook " + pb + " with " + pbr.cursor.getCount() + " results"); return true; }
// process CPBR command after permission check /*package*/ int processCpbrCommand() { log("processCpbrCommand"); int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; int atCommandErrorCode = -1; String atCommandResponse = null; StringBuilder response = new StringBuilder(); String record; // Shortcut SM phonebook if ("SM".equals(mCurrentPhonebook)) { atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; return atCommandResult; } // Check phonebook PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); // false); if (pbr == null) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; return atCommandResult; } // More sanity checks // Send OK instead of ERROR if these checks fail. // When we send error, certain kits like BMW disconnect the // Handsfree connection. if (pbr.cursor.getCount() == 0 || mCpbrIndex1 <= 0 || mCpbrIndex2 < mCpbrIndex1 || mCpbrIndex2 > pbr.cursor.getCount() || mCpbrIndex1 > pbr.cursor.getCount()) { atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; return atCommandResult; } // Process atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; int errorDetected = -1; // no error pbr.cursor.moveToPosition(mCpbrIndex1 - 1); log("mCpbrIndex1 = " + mCpbrIndex1 + " and mCpbrIndex2 = " + mCpbrIndex2); for (int index = mCpbrIndex1; index <= mCpbrIndex2; index++) { String number = pbr.cursor.getString(pbr.numberColumn); String name = null; int type = -1; if (pbr.nameColumn == -1 && number != null && number.length() > 0) { // try caller id lookup // TODO: This code is horribly inefficient. I saw it // take 7 seconds to process 100 missed calls. Cursor c = mContentResolver.query( Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number), new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE}, null, null, null); if (c != null) { if (c.moveToFirst()) { name = c.getString(0); type = c.getInt(1); } c.close(); } if (DBG && name == null) log("Caller ID lookup failed for " + number); } else if (pbr.nameColumn != -1) { name = pbr.cursor.getString(pbr.nameColumn); } else { log("processCpbrCommand: empty name and number"); } if (name == null) name = ""; name = name.trim(); if (name.length() > 28) name = name.substring(0, 28); if (pbr.typeColumn != -1) { type = pbr.cursor.getInt(pbr.typeColumn); name = name + "/" + getPhoneType(type); } if (number == null) number = ""; int regionType = PhoneNumberUtils.toaFromString(number); number = number.trim(); number = PhoneNumberUtils.stripSeparators(number); if (number.length() > 30) number = number.substring(0, 30); int numberPresentation = Calls.PRESENTATION_ALLOWED; if (pbr.numberPresentationColumn != -1) { numberPresentation = pbr.cursor.getInt(pbr.numberPresentationColumn); } if (numberPresentation != Calls.PRESENTATION_ALLOWED) { number = ""; // TODO: there are 3 types of numbers should have resource // strings for: unknown, private, and payphone name = mContext.getString(R.string.unknownNumber); } // TODO(): Handle IRA commands. It's basically // a 7 bit ASCII character set. if (!name.equals("") && mCharacterSet.equals("GSM")) { byte[] nameByte = GsmAlphabet.stringToGsm8BitPacked(name); if (nameByte == null) { name = mContext.getString(R.string.unknownNumber); } else { name = new String(nameByte); } } record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + name + "\""; record = record + "\r\n\r\n"; atCommandResponse = record; log("processCpbrCommand - atCommandResponse = " + atCommandResponse); mStateMachine.atResponseStringNative(atCommandResponse); if (!pbr.cursor.moveToNext()) { break; } } if (pbr != null && pbr.cursor != null) { pbr.cursor.close(); pbr.cursor = null; } return atCommandResult; }
public void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { log("handleCpbrCommand - atString = " + atString); int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; int atCommandErrorCode = -1; String atCommandResponse = null; switch (type) { case TYPE_TEST: // Test /* Ideally we should return the maximum range of valid index's * for the selected phone book, but this causes problems for the * Parrot CK3300. So instead send just the range of currently * valid index's. */ log("handleCpbrCommand - test command"); int size; if ("SM".equals(mCurrentPhonebook)) { size = 0; } else { PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, true); // false); if (pbr == null) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; break; } size = pbr.cursor.getCount(); log("handleCpbrCommand - size = " + size); pbr.cursor.close(); pbr.cursor = null; } if (size == 0) { /* Sending "+CPBR: (1-0)" can confused some carkits, send "1-1" * instead */ size = 1; } atCommandResponse = "+CPBR: (1-" + size + "),30,30"; atCommandResult = HeadsetHalConstants.AT_RESPONSE_OK; break; // Read PhoneBook Entries case TYPE_READ: case TYPE_SET: // Set & read // Phone Book Read Request // AT+CPBR=<index1>[,<index2>] log("handleCpbrCommand - set/read command"); if (mCpbrIndex1 != -1) { /* handling a CPBR at the moment, reject this CPBR command */ atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_ALLOWED; break; } // Parse indexes int index1; int index2; if ((atString.split("=")).length < 2) { mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode); break; } String atCommand = (atString.split("="))[1]; String[] indices = atCommand.split(","); for (int i = 0; i < indices.length; i++) // replace AT command separator ';' from the index if any indices[i] = indices[i].replace(';', ' ').trim(); try { index1 = Integer.parseInt(indices[0]); if (indices.length == 1) index2 = index1; else index2 = Integer.parseInt(indices[1]); } catch (Exception e) { log("handleCpbrCommand - exception - invalid chars: " + e.toString()); atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode); break; } mCpbrIndex1 = index1; mCpbrIndex2 = index2; mCheckingAccessPermission = true; if (checkAccessPermission(remoteDevice)) { mCheckingAccessPermission = false; atCommandResult = processCpbrCommand(); mCpbrIndex1 = mCpbrIndex2 = -1; break; } // no reponse here, will continue the process in handleAccessPermissionResult break; case TYPE_UNKNOWN: default: log("handleCpbrCommand - invalid chars"); atCommandErrorCode = BluetoothCmeError.TEXT_HAS_INVALID_CHARS; } if (atCommandResponse != null) mStateMachine.atResponseStringNative(atCommandResponse); mStateMachine.atResponseCodeNative(atCommandResult, atCommandErrorCode); }