/** Function to send obex header back to client such as get phonebook size request */ private final int pushHeader(final Operation op, final HeaderSet reply) { OutputStream outputStream = null; if (D) Log.d(TAG, "Push Header"); if (D) Log.d(TAG, reply.toString()); int pushResult = ResponseCodes.OBEX_HTTP_OK; try { op.sendHeaders(reply); outputStream = op.openOutputStream(); outputStream.flush(); } catch (IOException e) { Log.e(TAG, e.toString()); pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } finally { if (!closeStream(outputStream, op)) { pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } } return pushResult; }
public static boolean closeStream(final OutputStream out, final Operation op) { boolean returnvalue = true; try { if (out != null) { out.close(); } } catch (IOException e) { Log.e(TAG, "outputStream close failed" + e.toString()); returnvalue = false; } try { if (op != null) { op.close(); } } catch (IOException e) { Log.e(TAG, "operation close failed" + e.toString()); returnvalue = false; } return returnvalue; }
private final int handleAppParaForResponse( AppParamValue appParamValue, int size, HeaderSet reply, Operation op) { byte[] misnum = new byte[1]; ApplicationParameter ap = new ApplicationParameter(); // In such case, PCE only want the number of index. // So response not contain any Body header. if (mNeedPhonebookSize) { if (V) Log.v(TAG, "Need Phonebook size in response header."); mNeedPhonebookSize = false; byte[] pbsize = new byte[2]; pbsize[0] = (byte) ((size / 256) & 0xff); // HIGH VALUE pbsize[1] = (byte) ((size % 256) & 0xff); // LOW VALUE ap.addAPPHeader( ApplicationParameter.TRIPLET_TAGID.PHONEBOOKSIZE_TAGID, ApplicationParameter.TRIPLET_LENGTH.PHONEBOOKSIZE_LENGTH, pbsize); if (mNeedNewMissedCallsNum) { mNeedNewMissedCallsNum = false; int nmnum = size - mMissedCallSize; mMissedCallSize = size; nmnum = nmnum > 0 ? nmnum : 0; misnum[0] = (byte) nmnum; ap.addAPPHeader( ApplicationParameter.TRIPLET_TAGID.NEWMISSEDCALLS_TAGID, ApplicationParameter.TRIPLET_LENGTH.NEWMISSEDCALLS_LENGTH, misnum); if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true, num= " + nmnum); } reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam()); if (D) Log.d(TAG, "Send back Phonebook size only, without body info! Size= " + size); return pushHeader(op, reply); } // Only apply to "mch" download/listing. // NewMissedCalls is used only in the response, together with Body // header. if (mNeedNewMissedCallsNum) { if (V) Log.v(TAG, "Need new missed call num in response header."); mNeedNewMissedCallsNum = false; int nmnum = size - mMissedCallSize; mMissedCallSize = size; nmnum = nmnum > 0 ? nmnum : 0; misnum[0] = (byte) nmnum; ap.addAPPHeader( ApplicationParameter.TRIPLET_TAGID.NEWMISSEDCALLS_TAGID, ApplicationParameter.TRIPLET_LENGTH.NEWMISSEDCALLS_LENGTH, misnum); reply.setHeader(HeaderSet.APPLICATION_PARAMETER, ap.getAPPparam()); if (D) Log.d(TAG, "handleAppParaForResponse(): mNeedNewMissedCallsNum=true, num= " + nmnum); // Only Specifies the headers, not write for now, will write to PCE // together with Body try { op.sendHeaders(reply); } catch (IOException e) { Log.e(TAG, e.toString()); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } } return NEED_SEND_BODY; }
/** Function to send vcard data to client */ private final int pushBytes(Operation op, final String vcardString) { if (vcardString == null) { Log.w(TAG, "vcardString is null!"); return ResponseCodes.OBEX_HTTP_OK; } int vcardStringLen = vcardString.length(); if (D) Log.d(TAG, "Send Data: len=" + vcardStringLen); OutputStream outputStream = null; int pushResult = ResponseCodes.OBEX_HTTP_OK; try { outputStream = op.openOutputStream(); } catch (IOException e) { Log.e(TAG, "open outputstrem failed" + e.toString()); return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } int position = 0; long timestamp = 0; int outputBufferSize = op.getMaxPacketSize(); if (V) Log.v(TAG, "outputBufferSize = " + outputBufferSize); while (position != vcardStringLen) { if (sIsAborted) { ((ServerOperation) op).isAborted = true; sIsAborted = false; break; } if (V) timestamp = System.currentTimeMillis(); int readLength = outputBufferSize; if (vcardStringLen - position < outputBufferSize) { readLength = vcardStringLen - position; } String subStr = vcardString.substring(position, position + readLength); try { outputStream.write(subStr.getBytes(), 0, readLength); } catch (IOException e) { Log.e(TAG, "write outputstrem failed" + e.toString()); pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; break; } if (V) { Log.v( TAG, "Sending vcard String position = " + position + " readLength " + readLength + " bytes took " + (System.currentTimeMillis() - timestamp) + " ms"); } position += readLength; } if (V) Log.v(TAG, "Send Data complete!"); if (!closeStream(outputStream, op)) { pushResult = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } return pushResult; }
@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; } }