private byte[] buildEmailData(int length, int adnRecIndex, String email) {
   byte[] data = new byte[length];
   for (int i = 0; i < length; i++) {
     data[i] = (byte) 0xff;
   }
   if (TextUtils.isEmpty(email)) {
     Log.w(LOG_TAG, "[buildEmailData] Empty email record");
     return data; // return the empty record (for delete)
   }
   byte[] byteEmail = GsmAlphabet.stringToGsm8BitPacked(email);
   System.arraycopy(byteEmail, 0, data, 0, byteEmail.length);
   int pbrIndex = getPbrIndexBy(adnRecIndex);
   int recordIndex = adnRecIndex - getInitIndexBy(pbrIndex);
   if (mEmailPresentInIap) {
     data[length - 1] = (byte) (recordIndex + 1);
   }
   Log.w(LOG_TAG, " buildEmailData: data is" + IccUtils.bytesToHexString(data));
   return data;
 }
  @Override
  public void format(ByteArrayOutputStream buf) {
    if (buf == null) {
      return;
    }

    // Text string object
    int tag = 0x80 | ComprehensionTlvTag.LANGUAGE.value();
    buf.write(tag); // tag

    byte[] data;

    if (mLang != null && mLang.length() > 0) {
      data = GsmAlphabet.stringToGsm8BitPacked(mLang);
    } else {
      data = new byte[0];
    }

    buf.write(data.length);

    for (byte b : data) {
      buf.write(b);
    }
  }
Пример #3
0
  // process CPBR command after permission check
  private AtCommandResult processCpbrCommand() {
    // Shortcut SM phonebook
    if ("SM".equals(mCurrentPhonebook)) {
      return new AtCommandResult(AtCommandResult.OK);
    }

    // Check phonebook
    PhonebookResult pbr = getPhonebookResult(mCurrentPhonebook, false);
    if (pbr == null) {
      return mHandsfree.reportCmeError(BluetoothCmeError.OPERATION_NOT_ALLOWED);
    }

    // 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 (SystemProperties.BLUETI_ENHANCEMENT) {
      if (pbr.cursor.getCount() == 0
          || mCpbrIndex1 <= 0
          || mCpbrIndex2 < mCpbrIndex1
          || mCpbrIndex1 > pbr.cursor.getCount()) {
        return new AtCommandResult(AtCommandResult.OK);
      }
    } else {
      if (pbr.cursor.getCount() == 0
          || mCpbrIndex1 <= 0
          || mCpbrIndex2 < mCpbrIndex1
          || mCpbrIndex2 > pbr.cursor.getCount()
          || mCpbrIndex1 > pbr.cursor.getCount()) {
        return new AtCommandResult(AtCommandResult.OK);
      }
    }

    if (SystemProperties.BLUETI_ENHANCEMENT) {
      /* If index2 is more then what we currentely have in our device
       * We will return only the ones that we have and not just AT->OK
       */
      if (mCpbrIndex2 > pbr.cursor.getCount()) {
        Log.d(
            TAG,
            "mCpbrIndex2 is: "
                + mCpbrIndex2
                + " its more then we actually got : "
                + pbr.cursor.getCount());
        Log.d(TAG, "Returning only what we got : " + pbr.cursor.getCount());
        mCpbrIndex2 = pbr.cursor.getCount();
      }
    }

    // Process
    AtCommandResult result = new AtCommandResult(AtCommandResult.OK);
    int errorDetected = -1; // no error
    pbr.cursor.moveToPosition(mCpbrIndex1 - 1);
    for (int index = mCpbrIndex1; index <= mCpbrIndex2; index++) {
      String number = pbr.cursor.getString(pbr.numberColumn);
      String name = null;
      int type = -1;
      if (pbr.nameColumn == -1) {
        // try caller id lookup
        // TODO: This code is horribly inefficient. I saw it
        // take 7 seconds to process 100 missed calls.
        Cursor c =
            mContext
                .getContentResolver()
                .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 {
        name = pbr.cursor.getString(pbr.nameColumn);
      }
      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);
      if (number.equals("-1")) {
        // unknown numbers are stored as -1 in our database
        number = "";
        name = mContext.getString(R.string.unknown);
      }

      // 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.unknown);
        } else {
          name = new String(nameByte);
        }
      }

      result.addResponse(
          "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + name + "\"");
      if (!pbr.cursor.moveToNext()) {
        break;
      }
    }
    return result;
  }
  @Override
  public void format(ByteArrayOutputStream buf) {
    if (buf == null) {
      return;
    }

    // Text string object
    int tag = 0x80 | ComprehensionTlvTag.TEXT_STRING.value();
    buf.write(tag); // tag

    byte[] data;

    if (mIsYesNo) {
      data = new byte[1];
      data[0] = mYesNoResponse ? GET_INKEY_YES : GET_INKEY_NO;
    } else if (mInData != null && mInData.length() > 0) {
      try {
        // ETSI TS 102 223 8.15, should use the same format as in SMS messages
        // on the network.
        if (mIsUcs2) {
          // ucs2 is by definition big endian.
          data = mInData.getBytes("UTF-16BE");
        } else if (mIsPacked) {
          byte[] tempData = GsmAlphabet.stringToGsm7BitPacked(mInData, 0, 0);
          // The size of the new buffer will be smaller than the original buffer
          // since 7-bit GSM packed only requires ((mInData.length * 7) + 7) / 8 bytes.
          // And we don't need to copy/store the first byte from the returned array
          // because it is used to store the count of septets used.
          data = new byte[tempData.length - 1];
          System.arraycopy(tempData, 1, data, 0, tempData.length - 1);
        } else {
          data = GsmAlphabet.stringToGsm8BitPacked(mInData);
        }
      } catch (UnsupportedEncodingException e) {
        data = new byte[0];
      } catch (EncodeException e) {
        data = new byte[0];
      }
    } else {
      data = new byte[0];
    }

    // length - one more for data coding scheme.

    // ETSI TS 102 223 Annex C (normative): Structure of CAT communications
    // Any length within the APDU limits (up to 255 bytes) can thus be encoded on two bytes.
    // This coding is chosen to remain compatible with TS 101.220.
    // Note that we need to reserve one more byte for coding scheme thus the maximum APDU
    // size would be 254 bytes.
    if (data.length + 1 <= 255) {
      writeLength(buf, data.length + 1);
    } else {
      data = new byte[0];
    }

    // data coding scheme
    if (mIsUcs2) {
      buf.write(0x08); // UCS2
    } else if (mIsPacked) {
      buf.write(0x00); // 7 bit packed
    } else {
      buf.write(0x04); // 8 bit unpacked
    }

    for (byte b : data) {
      buf.write(b);
    }
  }
Пример #5
0
  // 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;
  }