@Override
  public int onConnect(final HeaderSet request, HeaderSet reply) {
    if (V) logHeader(request);
    try {
      byte[] uuid = (byte[]) request.getHeader(HeaderSet.TARGET);
      if (uuid == null) {
        return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
      }
      if (D) Log.d(TAG, "onConnect(): uuid=" + Arrays.toString(uuid));

      if (uuid.length != UUID_LENGTH) {
        Log.w(TAG, "Wrong UUID length");
        return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
      }
      for (int i = 0; i < UUID_LENGTH; i++) {
        if (uuid[i] != PBAP_TARGET[i]) {
          Log.w(TAG, "Wrong UUID");
          return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
        }
      }
      reply.setHeader(HeaderSet.WHO, uuid);
    } catch (IOException e) {
      Log.e(TAG, e.toString());
      return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
    }

    try {
      byte[] remote = (byte[]) request.getHeader(HeaderSet.WHO);
      if (remote != null) {
        if (D) Log.d(TAG, "onConnect(): remote=" + Arrays.toString(remote));
        reply.setHeader(HeaderSet.TARGET, remote);
      }
    } catch (IOException e) {
      Log.e(TAG, e.toString());
      return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
    }

    if (V) Log.v(TAG, "onConnect(): uuid is ok, will send out " + "MSG_SESSION_ESTABLISHED msg.");

    Message msg = Message.obtain(mCallback);
    msg.what = BluetoothPbapService.MSG_SESSION_ESTABLISHED;
    msg.sendToTarget();

    return ResponseCodes.OBEX_HTTP_OK;
  }
  public static final void logHeader(HeaderSet hs) {
    Log.v(TAG, "Dumping HeaderSet " + hs.toString());
    try {

      Log.v(TAG, "COUNT : " + hs.getHeader(HeaderSet.COUNT));
      Log.v(TAG, "NAME : " + hs.getHeader(HeaderSet.NAME));
      Log.v(TAG, "TYPE : " + hs.getHeader(HeaderSet.TYPE));
      Log.v(TAG, "LENGTH : " + hs.getHeader(HeaderSet.LENGTH));
      Log.v(TAG, "TIME_ISO_8601 : " + hs.getHeader(HeaderSet.TIME_ISO_8601));
      Log.v(TAG, "TIME_4_BYTE : " + hs.getHeader(HeaderSet.TIME_4_BYTE));
      Log.v(TAG, "DESCRIPTION : " + hs.getHeader(HeaderSet.DESCRIPTION));
      Log.v(TAG, "TARGET : " + hs.getHeader(HeaderSet.TARGET));
      Log.v(TAG, "HTTP : " + hs.getHeader(HeaderSet.HTTP));
      Log.v(TAG, "WHO : " + hs.getHeader(HeaderSet.WHO));
      Log.v(TAG, "OBJECT_CLASS : " + hs.getHeader(HeaderSet.OBJECT_CLASS));
      Log.v(TAG, "APPLICATION_PARAMETER : " + hs.getHeader(HeaderSet.APPLICATION_PARAMETER));
    } catch (IOException e) {
      Log.e(TAG, "dump HeaderSet error " + e);
    }
  }
  @Override
  public int onSetPath(
      final HeaderSet request, final HeaderSet reply, final boolean backup, final boolean create) {
    if (V) logHeader(request);
    if (D) Log.d(TAG, "before setPath, mCurrentPath ==  " + mCurrentPath);

    String current_path_tmp = mCurrentPath;
    String tmp_path = null;
    try {
      tmp_path = (String) request.getHeader(HeaderSet.NAME);
    } catch (IOException e) {
      Log.e(TAG, "Get name header fail");
      return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
    }
    if (D) Log.d(TAG, "backup=" + backup + " create=" + create + " name=" + tmp_path);

    if (backup) {
      if (current_path_tmp.length() != 0) {
        current_path_tmp = current_path_tmp.substring(0, current_path_tmp.lastIndexOf("/"));
      }
    } else {
      if (tmp_path == null) {
        current_path_tmp = "";
      } else {
        current_path_tmp = current_path_tmp + "/" + tmp_path;
      }
    }

    if ((current_path_tmp.length() != 0) && (!isLegalPath(current_path_tmp))) {
      if (create) {
        Log.w(TAG, "path create is forbidden!");
        return ResponseCodes.OBEX_HTTP_FORBIDDEN;
      } else {
        Log.w(TAG, "path is not legal");
        return ResponseCodes.OBEX_HTTP_NOT_FOUND;
      }
    }
    mCurrentPath = current_path_tmp;
    if (V) Log.v(TAG, "after setPath, mCurrentPath ==  " + mCurrentPath);

    return ResponseCodes.OBEX_HTTP_OK;
  }
  @Override
  public int onGet(Operation op) {
    sIsAborted = false;
    HeaderSet request = null;
    HeaderSet reply = new HeaderSet();
    String type = "";
    String name = "";
    byte[] appParam = null;
    AppParamValue appParamValue = new AppParamValue();
    try {
      request = op.getReceivedHeader();
      type = (String) request.getHeader(HeaderSet.TYPE);
      name = (String) request.getHeader(HeaderSet.NAME);
      appParam = (byte[]) request.getHeader(HeaderSet.APPLICATION_PARAMETER);
    } catch (IOException e) {
      Log.e(TAG, "request headers error");
      return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
    }

    if (V) logHeader(request);
    if (D) Log.d(TAG, "OnGet type is " + type + "; name is " + name);

    if (type == null) {
      return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
    }
    // Accroding to specification,the name header could be omitted such as
    // sony erriccsonHBH-DS980

    // For "x-bt/phonebook" and "x-bt/vcard-listing":
    // if name == null, guess what carkit actually want from current path
    // For "x-bt/vcard":
    // We decide which kind of content client would like per current path

    boolean validName = true;
    if (TextUtils.isEmpty(name)) {
      validName = false;
    }

    if (!validName || (validName && type.equals(TYPE_VCARD))) {
      if (D) Log.d(TAG, "Guess what carkit actually want from current path (" + mCurrentPath + ")");

      if (mCurrentPath.equals(PB_PATH)) {
        appParamValue.needTag = ContentType.PHONEBOOK;
      } else if (mCurrentPath.equals(ICH_PATH)) {
        appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
      } else if (mCurrentPath.equals(OCH_PATH)) {
        appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
      } else if (mCurrentPath.equals(MCH_PATH)) {
        appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
        mNeedNewMissedCallsNum = true;
      } else if (mCurrentPath.equals(CCH_PATH)) {
        appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
      } 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()))) {
        appParamValue.needTag = ContentType.PHONEBOOK;
        if (D) Log.v(TAG, "download phonebook request");
      } else if (name.contains(ICH.subSequence(0, ICH.length()))) {
        appParamValue.needTag = ContentType.INCOMING_CALL_HISTORY;
        if (D) Log.v(TAG, "download incoming calls request");
      } else if (name.contains(OCH.subSequence(0, OCH.length()))) {
        appParamValue.needTag = ContentType.OUTGOING_CALL_HISTORY;
        if (D) Log.v(TAG, "download outgoing calls request");
      } else if (name.contains(MCH.subSequence(0, MCH.length()))) {
        appParamValue.needTag = ContentType.MISSED_CALL_HISTORY;
        mNeedNewMissedCallsNum = true;
        if (D) Log.v(TAG, "download missed calls request");
      } else if (name.contains(CCH.subSequence(0, CCH.length()))) {
        appParamValue.needTag = ContentType.COMBINED_CALL_HISTORY;
        if (D) Log.v(TAG, "download combined calls request");
      } else {
        Log.w(TAG, "Input name doesn't contain valid info!!!");
        return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
      }
    }

    if ((appParam != null) && !parseApplicationParameter(appParam, appParamValue)) {
      return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
    }

    // listing request
    if (type.equals(TYPE_LISTING)) {
      return pullVcardListing(appParam, appParamValue, reply, op);
    }
    // pull vcard entry request
    else if (type.equals(TYPE_VCARD)) {
      return pullVcardEntry(appParam, appParamValue, op, name, mCurrentPath);
    }
    // down load phone book request
    else if (type.equals(TYPE_PB)) {
      return pullPhonebook(appParam, appParamValue, reply, op, name);
    } else {
      Log.w(TAG, "unknown type request!!!");
      return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
    }
  }