diff --git a/obex/Android.bp b/obex/Android.bp
index 37e7f76..d89d41d 100644
--- a/obex/Android.bp
+++ b/obex/Android.bp
@@ -44,6 +44,8 @@
     ],
 }
 
+// No longer used. Only kept because the ObexPacket class is a public API.
+// The library has been migrated to platform/external/obex.
 java_sdk_library {
     name: "javax.obex",
     srcs: ["javax/**/*.java"],
diff --git a/obex/javax/obex/ApplicationParameter.java b/obex/javax/obex/ApplicationParameter.java
deleted file mode 100644
index 16770a1a..0000000
--- a/obex/javax/obex/ApplicationParameter.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-/**
- * @hide
- */
-public final class ApplicationParameter {
-
-    private byte[] mArray;
-
-    private int mLength;
-
-    private int mMaxLength = 1000;
-
-    public static class TRIPLET_TAGID {
-        public static final byte ORDER_TAGID = 0x01;
-
-        public static final byte SEARCH_VALUE_TAGID = 0x02;
-
-        public static final byte SEARCH_ATTRIBUTE_TAGID = 0x03;
-
-        // if equals to "0", PSE only reply number of contacts
-        public static final byte MAXLISTCOUNT_TAGID = 0x04;
-
-        public static final byte LISTSTARTOFFSET_TAGID = 0x05;
-
-        public static final byte PROPERTY_SELECTOR_TAGID = 0x06;
-
-        public static final byte FORMAT_TAGID = 0x07;
-
-        // only used if max list count = 0
-        public static final byte PHONEBOOKSIZE_TAGID = 0x08;
-
-        // only used in "mch" in response
-        public static final byte NEWMISSEDCALLS_TAGID = 0x09;
-
-        public static final byte SUPPORTEDFEATURE_TAGID = 0x10;
-
-        public static final byte PRIMARYVERSIONCOUNTER_TAGID = 0x0A;
-
-        public static final byte SECONDARYVERSIONCOUNTER_TAGID = 0x0B;
-
-        public static final byte VCARDSELECTOR_TAGID = 0x0C;
-
-        public static final byte DATABASEIDENTIFIER_TAGID = 0x0D;
-
-        public static final byte VCARDSELECTOROPERATOR_TAGID = 0x0E;
-
-        public static final byte RESET_NEW_MISSED_CALLS_TAGID = 0x0F;
-    }
-
-    public static class TRIPLET_VALUE {
-        public static class ORDER {
-            public static final byte ORDER_BY_INDEX = 0x00;
-
-            public static final byte ORDER_BY_ALPHANUMERIC = 0x01;
-
-            public static final byte ORDER_BY_PHONETIC = 0x02;
-        }
-
-        public static class SEARCHATTRIBUTE {
-            public static final byte SEARCH_BY_NAME = 0x00;
-
-            public static final byte SEARCH_BY_NUMBER = 0x01;
-
-            public static final byte SEARCH_BY_SOUND = 0x02;
-        }
-
-        public static class FORMAT {
-            public static final byte VCARD_VERSION_21 = 0x00;
-
-            public static final byte VCARD_VERSION_30 = 0x01;
-        }
-    }
-
-    public static class TRIPLET_LENGTH {
-        public static final byte ORDER_LENGTH = 1;
-
-        public static final byte SEARCH_ATTRIBUTE_LENGTH = 1;
-
-        public static final byte MAXLISTCOUNT_LENGTH = 2;
-
-        public static final byte LISTSTARTOFFSET_LENGTH = 2;
-
-        public static final byte PROPERTY_SELECTOR_LENGTH = 8;
-
-        public static final byte FORMAT_LENGTH = 1;
-
-        public static final byte PHONEBOOKSIZE_LENGTH = 2;
-
-        public static final byte NEWMISSEDCALLS_LENGTH = 1;
-
-        public static final byte SUPPORTEDFEATURE_LENGTH = 4;
-
-        public static final byte PRIMARYVERSIONCOUNTER_LENGTH = 16;
-
-        public static final byte SECONDARYVERSIONCOUNTER_LENGTH = 16;
-
-        public static final byte VCARDSELECTOR_LENGTH = 8;
-
-        public static final byte DATABASEIDENTIFIER_LENGTH = 16;
-
-        public static final byte VCARDSELECTOROPERATOR_LENGTH = 1;
-
-        public static final byte RESETNEWMISSEDCALLS_LENGTH = 1;
-    }
-
-    public ApplicationParameter() {
-        mArray = new byte[mMaxLength];
-        mLength = 0;
-    }
-
-    public void addAPPHeader(byte tag, byte len, byte[] value) {
-        if ((mLength + len + 2) > mMaxLength) {
-            byte[] array_tmp = new byte[mLength + 4 * len];
-            System.arraycopy(mArray, 0, array_tmp, 0, mLength);
-            mArray = array_tmp;
-            mMaxLength = mLength + 4 * len;
-        }
-        mArray[mLength++] = tag;
-        mArray[mLength++] = len;
-        System.arraycopy(value, 0, mArray, mLength, len);
-        mLength += len;
-    }
-
-    public byte[] getAPPparam() {
-        byte[] para = new byte[mLength];
-        System.arraycopy(mArray, 0, para, 0, mLength);
-        return para;
-    }
-}
diff --git a/obex/javax/obex/Authenticator.java b/obex/javax/obex/Authenticator.java
deleted file mode 100644
index ec226fb..0000000
--- a/obex/javax/obex/Authenticator.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-/**
- * This interface provides a way to respond to authentication challenge and
- * authentication response headers. When a client or server receives an
- * authentication challenge or authentication response header, the
- * <code>onAuthenticationChallenge()</code> or
- * <code>onAuthenticationResponse()</code> will be called, respectively, by the
- * implementation.
- * <P>
- * For more information on how the authentication procedure works in OBEX,
- * please review the IrOBEX specification at <A
- * HREF="http://www.irda.org">http://www.irda.org</A>.
- * <P>
- * <STRONG>Authentication Challenges</STRONG>
- * <P>
- * When a client or server receives an authentication challenge header, the
- * <code>onAuthenticationChallenge()</code> method will be invoked by the OBEX
- * API implementation. The application will then return the user name (if
- * needed) and password via a <code>PasswordAuthentication</code> object. The
- * password in this object is not sent in the authentication response. Instead,
- * the 16-byte challenge received in the authentication challenge is combined
- * with the password returned from the <code>onAuthenticationChallenge()</code>
- * method and passed through the MD5 hash algorithm. The resulting value is sent
- * in the authentication response along with the user name if it was provided.
- * <P>
- * <STRONG>Authentication Responses</STRONG>
- * <P>
- * When a client or server receives an authentication response header, the
- * <code>onAuthenticationResponse()</code> method is invoked by the API
- * implementation with the user name received in the authentication response
- * header. (The user name will be <code>null</code> if no user name was provided
- * in the authentication response header.) The application must determine the
- * correct password. This value should be returned from the
- * <code>onAuthenticationResponse()</code> method. If the authentication request
- * should fail without the implementation checking the password,
- * <code>null</code> should be returned by the application. (This is needed for
- * reasons like not recognizing the user name, etc.) If the returned value is
- * not <code>null</code>, the OBEX API implementation will combine the password
- * returned from the <code>onAuthenticationResponse()</code> method and
- * challenge sent via the authentication challenge, apply the MD5 hash
- * algorithm, and compare the result to the response hash received in the
- * authentication response header. If the values are not equal, an
- * <code>IOException</code> will be thrown if the client requested
- * authentication. If the server requested authentication, the
- * <code>onAuthenticationFailure()</code> method will be called on the
- * <code>ServerRequestHandler</code> that failed authentication. The connection
- * is <B>not</B> closed if authentication failed.
- * @hide
- */
-public interface Authenticator {
-
-    /**
-     * Called when a client or a server receives an authentication challenge
-     * header. It should respond to the challenge with a
-     * <code>PasswordAuthentication</code> that contains the correct user name
-     * and password for the challenge.
-     * @param description the description of which user name and password should
-     *        be used; if no description is provided in the authentication
-     *        challenge or the description is encoded in an encoding scheme that
-     *        is not supported, an empty string will be provided
-     * @param isUserIdRequired <code>true</code> if the user ID is required;
-     *        <code>false</code> if the user ID is not required
-     * @param isFullAccess <code>true</code> if full access to the server will
-     *        be granted; <code>false</code> if read only access will be granted
-     * @return a <code>PasswordAuthentication</code> object containing the user
-     *         name and password used for authentication
-     */
-    PasswordAuthentication onAuthenticationChallenge(String description, boolean isUserIdRequired,
-            boolean isFullAccess);
-
-    /**
-     * Called when a client or server receives an authentication response
-     * header. This method will provide the user name and expect the correct
-     * password to be returned.
-     * @param userName the user name provided in the authentication response; may
-     *        be <code>null</code>
-     * @return the correct password for the user name provided; if
-     *         <code>null</code> is returned then the authentication request
-     *         failed
-     */
-    byte[] onAuthenticationResponse(byte[] userName);
-}
diff --git a/obex/javax/obex/BaseStream.java b/obex/javax/obex/BaseStream.java
deleted file mode 100644
index 022ad4f..0000000
--- a/obex/javax/obex/BaseStream.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-
-/**
- * This interface defines the methods needed by a parent that uses the
- * PrivateInputStream and PrivateOutputStream objects defined in this package.
- * @hide
- */
-public interface BaseStream {
-
-    /**
-     * Verifies that this object is still open.
-     * @throws IOException if the object is closed
-     */
-    void ensureOpen() throws IOException;
-
-    /**
-     * Verifies that additional information may be sent. In other words, the
-     * operation is not done.
-     * @throws IOException if the operation is completed
-     */
-    void ensureNotDone() throws IOException;
-
-    /**
-     * Continues the operation since there is no data to read.
-     * @param sendEmpty <code>true</code> if the operation should send an empty
-     *        packet or not send anything if there is no data to send
-     * @param inStream <code>true</code> if the stream is input stream or is
-     *        output stream
-     * @return <code>true</code> if the operation was completed;
-     *         <code>false</code> if no operation took place
-     * @throws IOException if an IO error occurs
-     */
-    boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException;
-
-    /**
-     * Called when the output or input stream is closed.
-     * @param inStream <code>true</code> if the input stream is closed;
-     *        <code>false</code> if the output stream is closed
-     * @throws IOException if an IO error occurs
-     */
-    void streamClosed(boolean inStream) throws IOException;
-}
diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java
deleted file mode 100644
index c627dfb..0000000
--- a/obex/javax/obex/ClientOperation.java
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2015 The Android Open Source Project
- * Copyright (C) 2015 Samsung LSI
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.ByteArrayOutputStream;
-
-import android.util.Log;
-
-/**
- * This class implements the <code>Operation</code> interface. It will read and
- * write data via puts and gets.
- * @hide
- */
-public final class ClientOperation implements Operation, BaseStream {
-
-    private static final String TAG = "ClientOperation";
-
-    private static final boolean V = ObexHelper.VDBG;
-
-    private ClientSession mParent;
-
-    private boolean mInputOpen;
-
-    private PrivateInputStream mPrivateInput;
-
-    private boolean mPrivateInputOpen;
-
-    private PrivateOutputStream mPrivateOutput;
-
-    private boolean mPrivateOutputOpen;
-
-    private String mExceptionMessage;
-
-    private int mMaxPacketSize;
-
-    private boolean mOperationDone;
-
-    private boolean mGetOperation;
-
-    private boolean mGetFinalFlag;
-
-    private HeaderSet mRequestHeader;
-
-    private HeaderSet mReplyHeader;
-
-    private boolean mEndOfBodySent;
-
-    private boolean mSendBodyHeader = true;
-    // A latch - when triggered, there is not way back ;-)
-    private boolean mSrmActive = false;
-
-    // Assume SRM disabled - until support is confirmed
-    // by the server
-    private boolean mSrmEnabled = false;
-    // keep waiting until final-bit is received in request
-    // to handle the case where the SRM enable header is in
-    // a different OBEX packet than the SRMP header.
-    private boolean mSrmWaitingForRemote = true;
-
-
-    /**
-     * Creates new OperationImpl to read and write data to a server
-     * @param maxSize the maximum packet size
-     * @param p the parent to this object
-     * @param type <code>true</code> if this is a get request;
-     *        <code>false</code. if this is a put request
-     * @param header the header to set in the initial request
-     * @throws IOException if the an IO error occurred
-     */
-    public ClientOperation(int maxSize, ClientSession p, HeaderSet header, boolean type)
-            throws IOException {
-
-        mParent = p;
-        mEndOfBodySent = false;
-        mInputOpen = true;
-        mOperationDone = false;
-        mMaxPacketSize = maxSize;
-        mGetOperation = type;
-        mGetFinalFlag = false;
-
-        mPrivateInputOpen = false;
-        mPrivateOutputOpen = false;
-        mPrivateInput = null;
-        mPrivateOutput = null;
-
-        mReplyHeader = new HeaderSet();
-
-        mRequestHeader = new HeaderSet();
-
-        int[] headerList = header.getHeaderList();
-
-        if (headerList != null) {
-
-            for (int i = 0; i < headerList.length; i++) {
-                mRequestHeader.setHeader(headerList[i], header.getHeader(headerList[i]));
-            }
-        }
-
-        if ((header).mAuthChall != null) {
-            mRequestHeader.mAuthChall = new byte[(header).mAuthChall.length];
-            System.arraycopy((header).mAuthChall, 0, mRequestHeader.mAuthChall, 0,
-                    (header).mAuthChall.length);
-        }
-
-        if ((header).mAuthResp != null) {
-            mRequestHeader.mAuthResp = new byte[(header).mAuthResp.length];
-            System.arraycopy((header).mAuthResp, 0, mRequestHeader.mAuthResp, 0,
-                    (header).mAuthResp.length);
-
-        }
-
-        if ((header).mConnectionID != null) {
-            mRequestHeader.mConnectionID = new byte[4];
-            System.arraycopy((header).mConnectionID, 0, mRequestHeader.mConnectionID, 0,
-                    4);
-
-        }
-    }
-
-    /**
-     * Allows to set flag which will force GET to be always sent as single packet request with
-     * final flag set. This is to improve compatibility with some profiles, i.e. PBAP which
-     * require requests to be sent this way.
-     */
-    public void setGetFinalFlag(boolean flag) {
-        mGetFinalFlag = flag;
-    }
-
-    /**
-     * Sends an ABORT message to the server. By calling this method, the
-     * corresponding input and output streams will be closed along with this
-     * object.
-     * @throws IOException if the transaction has already ended or if an OBEX
-     *         server called this method
-     */
-    public synchronized void abort() throws IOException {
-        ensureOpen();
-        //no compatible with sun-ri
-        if ((mOperationDone) && (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE)) {
-            throw new IOException("Operation has already ended");
-        }
-
-        mExceptionMessage = "Operation aborted";
-        if ((!mOperationDone) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
-            mOperationDone = true;
-            /*
-             * Since we are not sending any headers or returning any headers then
-             * we just need to write and read the same bytes
-             */
-            mParent.sendRequest(ObexHelper.OBEX_OPCODE_ABORT, null, mReplyHeader, null, false);
-
-            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_OK) {
-                throw new IOException("Invalid response code from server");
-            }
-
-            mExceptionMessage = null;
-        }
-
-        close();
-    }
-
-    /**
-     * Retrieves the response code retrieved from the server. Response codes are
-     * defined in the <code>ResponseCodes</code> interface.
-     * @return the response code retrieved from the server
-     * @throws IOException if an error occurred in the transport layer during
-     *         the transaction; if this method is called on a
-     *         <code>HeaderSet</code> object created by calling
-     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
-     *         object
-     */
-    public synchronized int getResponseCode() throws IOException {
-        if ((mReplyHeader.responseCode == -1)
-                || (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
-            validateConnection();
-        }
-
-        return mReplyHeader.responseCode;
-    }
-
-    /**
-     * This method will always return <code>null</code>
-     * @return <code>null</code>
-     */
-    public String getEncoding() {
-        return null;
-    }
-
-    /**
-     * Returns the type of content that the resource connected to is providing.
-     * E.g. if the connection is via HTTP, then the value of the content-type
-     * header field is returned.
-     * @return the content type of the resource that the URL references, or
-     *         <code>null</code> if not known
-     */
-    public String getType() {
-        try {
-            return (String)mReplyHeader.getHeader(HeaderSet.TYPE);
-        } catch (IOException e) {
-            if(V) Log.d(TAG, "Exception occured - returning null",e);
-            return null;
-        }
-    }
-
-    /**
-     * Returns the length of the content which is being provided. E.g. if the
-     * connection is via HTTP, then the value of the content-length header field
-     * is returned.
-     * @return the content length of the resource that this connection's URL
-     *         references, or -1 if the content length is not known
-     */
-    public long getLength() {
-        try {
-            Long temp = (Long)mReplyHeader.getHeader(HeaderSet.LENGTH);
-
-            if (temp == null) {
-                return -1;
-            } else {
-                return temp.longValue();
-            }
-        } catch (IOException e) {
-            if(V) Log.d(TAG,"Exception occured - returning -1",e);
-            return -1;
-        }
-    }
-
-    /**
-     * Open and return an input stream for a connection.
-     * @return an input stream
-     * @throws IOException if an I/O error occurs
-     */
-    public InputStream openInputStream() throws IOException {
-
-        ensureOpen();
-
-        if (mPrivateInputOpen)
-            throw new IOException("no more input streams available");
-        if (mGetOperation) {
-            // send the GET request here
-            validateConnection();
-        } else {
-            if (mPrivateInput == null) {
-                mPrivateInput = new PrivateInputStream(this);
-            }
-        }
-
-        mPrivateInputOpen = true;
-
-        return mPrivateInput;
-    }
-
-    /**
-     * Open and return a data input stream for a connection.
-     * @return an input stream
-     * @throws IOException if an I/O error occurs
-     */
-    public DataInputStream openDataInputStream() throws IOException {
-        return new DataInputStream(openInputStream());
-    }
-
-    /**
-     * Open and return an output stream for a connection.
-     * @return an output stream
-     * @throws IOException if an I/O error occurs
-     */
-    public OutputStream openOutputStream() throws IOException {
-
-        ensureOpen();
-        ensureNotDone();
-
-        if (mPrivateOutputOpen)
-            throw new IOException("no more output streams available");
-
-        if (mPrivateOutput == null) {
-            // there are 3 bytes operation headers and 3 bytes body headers //
-            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
-        }
-
-        mPrivateOutputOpen = true;
-
-        return mPrivateOutput;
-    }
-
-    public int getMaxPacketSize() {
-        return mMaxPacketSize - 6 - getHeaderLength();
-    }
-
-    public int getHeaderLength() {
-        // OPP may need it
-        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
-        return headerArray.length;
-    }
-
-    /**
-     * Open and return a data output stream for a connection.
-     * @return an output stream
-     * @throws IOException if an I/O error occurs
-     */
-    public DataOutputStream openDataOutputStream() throws IOException {
-        return new DataOutputStream(openOutputStream());
-    }
-
-    /**
-     * Closes the connection and ends the transaction
-     * @throws IOException if the operation has already ended or is closed
-     */
-    public void close() throws IOException {
-        mInputOpen = false;
-        mPrivateInputOpen = false;
-        mPrivateOutputOpen = false;
-        mParent.setRequestInactive();
-    }
-
-    /**
-     * Returns the headers that have been received during the operation.
-     * Modifying the object returned has no effect on the headers that are sent
-     * or retrieved.
-     * @return the headers received during this <code>Operation</code>
-     * @throws IOException if this <code>Operation</code> has been closed
-     */
-    public HeaderSet getReceivedHeader() throws IOException {
-        ensureOpen();
-
-        return mReplyHeader;
-    }
-
-    /**
-     * Specifies the headers that should be sent in the next OBEX message that
-     * is sent.
-     * @param headers the headers to send in the next message
-     * @throws IOException if this <code>Operation</code> has been closed or the
-     *         transaction has ended and no further messages will be exchanged
-     * @throws IllegalArgumentException if <code>headers</code> was not created
-     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
-     * @throws NullPointerException if <code>headers</code> is <code>null</code>
-     */
-    public void sendHeaders(HeaderSet headers) throws IOException {
-        ensureOpen();
-        if (mOperationDone) {
-            throw new IOException("Operation has already exchanged all data");
-        }
-
-        if (headers == null) {
-            throw new IOException("Headers may not be null");
-        }
-
-        int[] headerList = headers.getHeaderList();
-        if (headerList != null) {
-            for (int i = 0; i < headerList.length; i++) {
-                mRequestHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
-            }
-        }
-    }
-
-    /**
-     * Verifies that additional information may be sent. In other words, the
-     * operation is not done.
-     * @throws IOException if the operation is completed
-     */
-    public void ensureNotDone() throws IOException {
-        if (mOperationDone) {
-            throw new IOException("Operation has completed");
-        }
-    }
-
-    /**
-     * Verifies that the connection is open and no exceptions should be thrown.
-     * @throws IOException if an exception needs to be thrown
-     */
-    public void ensureOpen() throws IOException {
-        mParent.ensureOpen();
-
-        if (mExceptionMessage != null) {
-            throw new IOException(mExceptionMessage);
-        }
-        if (!mInputOpen) {
-            throw new IOException("Operation has already ended");
-        }
-    }
-
-    /**
-     * Verifies that the connection is open and the proper data has been read.
-     * @throws IOException if an IO error occurs
-     */
-    private void validateConnection() throws IOException {
-        ensureOpen();
-
-        // Make sure that a response has been recieved from remote
-        // before continuing
-        if (mPrivateInput == null || mReplyHeader.responseCode == -1) {
-            startProcessing();
-        }
-    }
-
-    /**
-     * Sends a request to the client of the specified type.
-     * This function will enable SRM and set SRM active if the server
-     * response allows this.
-     * @param opCode the request code to send to the client
-     * @return <code>true</code> if there is more data to send;
-     *         <code>false</code> if there is no more data to send
-     * @throws IOException if an IO error occurs
-     */
-    private boolean sendRequest(int opCode) throws IOException {
-        boolean returnValue = false;
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        int bodyLength = -1;
-        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, true);
-        if (mPrivateOutput != null) {
-            bodyLength = mPrivateOutput.size();
-        }
-
-        /*
-         * Determine if there is space to add a body request.  At present
-         * this method checks to see if there is room for at least a 17
-         * byte body header.  This number needs to be at least 6 so that
-         * there is room for the header ID and length and the reply ID and
-         * length, but it is a waste of resources if we can't send much of
-         * the body.
-         */
-        final int MINIMUM_BODY_LENGTH = 3;
-        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length + MINIMUM_BODY_LENGTH)
-                > mMaxPacketSize) {
-            int end = 0;
-            int start = 0;
-            // split & send the headerArray in multiple packets.
-
-            while (end != headerArray.length) {
-                //split the headerArray
-
-                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize
-                        - ObexHelper.BASE_PACKET_LENGTH);
-                // can not split
-                if (end == -1) {
-                    mOperationDone = true;
-                    abort();
-                    mExceptionMessage = "Header larger then can be sent in a packet";
-                    mInputOpen = false;
-
-                    if (mPrivateInput != null) {
-                        mPrivateInput.close();
-                    }
-
-                    if (mPrivateOutput != null) {
-                        mPrivateOutput.close();
-                    }
-                    throw new IOException("OBEX Packet exceeds max packet size");
-                }
-
-                byte[] sendHeader = new byte[end - start];
-                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
-                if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput, false)) {
-                    return false;
-                }
-
-                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                    return false;
-                }
-
-                start = end;
-            }
-
-            // Enable SRM if it should be enabled
-            checkForSrm();
-
-            if (bodyLength > 0) {
-                return true;
-            } else {
-                return false;
-            }
-        } else {
-            /* All headers will fit into a single package */
-            if(mSendBodyHeader == false) {
-                /* As we are not to send any body data, set the FINAL_BIT */
-                opCode |= ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK;
-            }
-            out.write(headerArray);
-        }
-
-        if (bodyLength > 0) {
-            /*
-             * Determine if we can send the whole body or just part of
-             * the body.  Remember that there is the 3 bytes for the
-             * response message and 3 bytes for the header ID and length
-             */
-            if (bodyLength > (mMaxPacketSize - headerArray.length - 6)) {
-                returnValue = true;
-
-                bodyLength = mMaxPacketSize - headerArray.length - 6;
-            }
-
-            byte[] body = mPrivateOutput.readBytes(bodyLength);
-
-            /*
-             * Since this is a put request if the final bit is set or
-             * the output stream is closed we need to send the 0x49
-             * (End of Body) otherwise, we need to send 0x48 (Body)
-             */
-            if ((mPrivateOutput.isClosed()) && (!returnValue) && (!mEndOfBodySent)
-                    && ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) != 0)) {
-                out.write(HeaderSet.END_OF_BODY);
-                mEndOfBodySent = true;
-            } else {
-                out.write(HeaderSet.BODY);
-            }
-
-            bodyLength += 3;
-            out.write((byte)(bodyLength >> 8));
-            out.write((byte)bodyLength);
-
-            if (body != null) {
-                out.write(body);
-            }
-        }
-
-        if (mPrivateOutputOpen && bodyLength <= 0 && !mEndOfBodySent) {
-            // only 0x82 or 0x83 can send 0x49
-            if ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) {
-                out.write(HeaderSet.BODY);
-            } else {
-                out.write(HeaderSet.END_OF_BODY);
-                mEndOfBodySent = true;
-            }
-
-            bodyLength = 3;
-            out.write((byte)(bodyLength >> 8));
-            out.write((byte)bodyLength);
-        }
-
-        if (out.size() == 0) {
-            if (!mParent.sendRequest(opCode, null, mReplyHeader, mPrivateInput, mSrmActive)) {
-                return false;
-            }
-            // Enable SRM if it should be enabled
-            checkForSrm();
-            return returnValue;
-        }
-        if ((out.size() > 0)
-                && (!mParent.sendRequest(opCode, out.toByteArray(),
-                        mReplyHeader, mPrivateInput, mSrmActive))) {
-            return false;
-        }
-        // Enable SRM if it should be enabled
-        checkForSrm();
-
-        // send all of the output data in 0x48,
-        // send 0x49 with empty body
-        if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0))
-            returnValue = true;
-
-        return returnValue;
-    }
-
-    private void checkForSrm() throws IOException {
-        Byte srmMode = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
-        if(mParent.isSrmSupported() == true && srmMode != null
-                && srmMode == ObexHelper.OBEX_SRM_ENABLE) {
-            mSrmEnabled = true;
-        }
-        /**
-         * Call this only when a complete obex packet have been received.
-         * (This is not optimal, but the current design is not really suited to
-         * the way SRM is specified.)
-         * The BT usage of SRM is not really safe - it assumes that the SRMP will fit
-         * into every OBEX packet, hence if another header occupies the entire packet,
-         * the scheme will not work - unlikely though.
-         */
-        if(mSrmEnabled) {
-            mSrmWaitingForRemote = false;
-            Byte srmp = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
-            if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) {
-                mSrmWaitingForRemote = true;
-                // Clear the wait header, as the absence of the header in the next packet
-                // indicates don't wait anymore.
-                mReplyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
-            }
-        }
-        if((mSrmWaitingForRemote == false) && (mSrmEnabled == true)) {
-            mSrmActive = true;
-        }
-    }
-
-    /**
-     * This method starts the processing thread results. It will send the
-     * initial request. If the response takes more then one packet, a thread
-     * will be started to handle additional requests
-     * @throws IOException if an IO error occurs
-     */
-    private synchronized void startProcessing() throws IOException {
-
-        if (mPrivateInput == null) {
-            mPrivateInput = new PrivateInputStream(this);
-        }
-        boolean more = true;
-
-        if (mGetOperation) {
-            if (!mOperationDone) {
-                if (!mGetFinalFlag) {
-                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                    while ((more) && (mReplyHeader.responseCode ==
-                            ResponseCodes.OBEX_HTTP_CONTINUE)) {
-                        more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
-                    }
-                    // For GET we need to loop until all headers have been sent,
-                    // And then we wait for the first continue package with the
-                    // reply.
-                    if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
-                        mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
-                                null, mReplyHeader, mPrivateInput, mSrmActive);
-                    }
-                    if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                        mOperationDone = true;
-                    } else {
-                        checkForSrm();
-                    }
-                } else {
-                    more = sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
-
-                    if (more) {
-                        throw new IOException("FINAL_GET forced, data didn't fit into one packet");
-                    }
-
-                    mOperationDone = true;
-                }
-            }
-        } else {
-            // PUT operation
-            if (!mOperationDone) {
-                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
-                    more = sendRequest(ObexHelper.OBEX_OPCODE_PUT);
-                }
-            }
-
-            if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
-                mParent.sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL,
-                        null, mReplyHeader, mPrivateInput, mSrmActive);
-            }
-
-            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                mOperationDone = true;
-            }
-        }
-    }
-
-    /**
-     * Continues the operation since there is no data to read.
-     * @param sendEmpty <code>true</code> if the operation should send an empty
-     *        packet or not send anything if there is no data to send
-     * @param inStream <code>true</code> if the stream is input stream or is
-     *        output stream
-     * @throws IOException if an IO error occurs
-     */
-    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
-            throws IOException {
-
-        // One path to the first put operation - the other one does not need to
-        // handle SRM, as all will fit into one packet.
-
-        if (mGetOperation) {
-            if ((inStream) && (!mOperationDone)) {
-                // to deal with inputstream in get operation
-                mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
-                        null, mReplyHeader, mPrivateInput, mSrmActive);
-                /*
-                  * Determine if that was not the last packet in the operation
-                  */
-                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                    mOperationDone = true;
-                } else {
-                    checkForSrm();
-                }
-
-                return true;
-
-            } else if ((!inStream) && (!mOperationDone)) {
-                // to deal with outputstream in get operation
-
-                if (mPrivateInput == null) {
-                    mPrivateInput = new PrivateInputStream(this);
-                }
-
-                if (!mGetFinalFlag) {
-                    sendRequest(ObexHelper.OBEX_OPCODE_GET);
-                } else {
-                    sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
-                }
-                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                    mOperationDone = true;
-                }
-                return true;
-
-            } else if (mOperationDone) {
-                return false;
-            }
-
-        } else {
-            // PUT operation
-            if ((!inStream) && (!mOperationDone)) {
-                // to deal with outputstream in put operation
-                if (mReplyHeader.responseCode == -1) {
-                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                }
-                sendRequest(ObexHelper.OBEX_OPCODE_PUT);
-                return true;
-            } else if ((inStream) && (!mOperationDone)) {
-                // How to deal with inputstream  in put operation ?
-                return false;
-
-            } else if (mOperationDone) {
-                return false;
-            }
-
-        }
-        return false;
-    }
-
-    /**
-     * Called when the output or input stream is closed.
-     * @param inStream <code>true</code> if the input stream is closed;
-     *        <code>false</code> if the output stream is closed
-     * @throws IOException if an IO error occurs
-     */
-    public void streamClosed(boolean inStream) throws IOException {
-        if (!mGetOperation) {
-            if ((!inStream) && (!mOperationDone)) {
-                // to deal with outputstream in put operation
-
-                boolean more = true;
-
-                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
-                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
-                    if (headerArray.length <= 0)
-                        more = false;
-                }
-                // If have not sent any data so send  all now
-                if (mReplyHeader.responseCode == -1) {
-                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                }
-
-                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
-                    more = sendRequest(ObexHelper.OBEX_OPCODE_PUT);
-                }
-
-                /*
-                 * According to the IrOBEX specification, after the final put, you
-                 * only have a single reply to send.  so we don't need the while
-                 * loop.
-                 */
-                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
-
-                    sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL);
-                }
-                mOperationDone = true;
-            } else if ((inStream) && (mOperationDone)) {
-                // how to deal with input stream in put stream ?
-                mOperationDone = true;
-            }
-        } else {
-            if ((inStream) && (!mOperationDone)) {
-
-                // to deal with inputstream in get operation
-                // Have not sent any data so send it all now
-
-                if (mReplyHeader.responseCode == -1) {
-                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                }
-
-                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) {
-                    if (!sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL)) {
-                        break;
-                    }
-                }
-                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) {
-                    mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL, null,
-                            mReplyHeader, mPrivateInput, false);
-                    // Regardless of the SRM state, wait for the response.
-                }
-                mOperationDone = true;
-            } else if ((!inStream) && (!mOperationDone)) {
-                // to deal with outputstream in get operation
-                // part of the data may have been sent in continueOperation.
-
-                boolean more = true;
-
-                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
-                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
-                    if (headerArray.length <= 0)
-                        more = false;
-                }
-
-                if (mPrivateInput == null) {
-                    mPrivateInput = new PrivateInputStream(this);
-                }
-                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0))
-                    more = false;
-
-                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
-                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
-                    more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
-                }
-                sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
-                //                parent.sendRequest(0x83, null, replyHeaders, privateInput);
-                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
-                    mOperationDone = true;
-                }
-            }
-        }
-    }
-
-    public void noBodyHeader(){
-        mSendBodyHeader = false;
-    }
-}
diff --git a/obex/javax/obex/ClientSession.java b/obex/javax/obex/ClientSession.java
deleted file mode 100644
index 272a920..0000000
--- a/obex/javax/obex/ClientSession.java
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * Copyright (c) 2015 The Android Open Source Project
- * Copyright (C) 2015 Samsung LSI
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import android.util.Log;
-
-/**
- * This class in an implementation of the OBEX ClientSession.
- * @hide
- */
-public final class ClientSession extends ObexSession {
-
-    private static final String TAG = "ClientSession";
-
-    private boolean mOpen;
-
-    // Determines if an OBEX layer connection has been established
-    private boolean mObexConnected;
-
-    private byte[] mConnectionId = null;
-
-    /*
-     * The max Packet size must be at least 255 according to the OBEX
-     * specification.
-     */
-    private int mMaxTxPacketSize = ObexHelper.LOWER_LIMIT_MAX_PACKET_SIZE;
-
-    private boolean mRequestActive;
-
-    private final InputStream mInput;
-
-    private final OutputStream mOutput;
-
-    private final boolean mLocalSrmSupported;
-
-    private final ObexTransport mTransport;
-
-    public ClientSession(final ObexTransport trans) throws IOException {
-        mInput = trans.openInputStream();
-        mOutput = trans.openOutputStream();
-        mOpen = true;
-        mRequestActive = false;
-        mLocalSrmSupported = trans.isSrmSupported();
-        mTransport = trans;
-    }
-
-    /**
-     * Create a ClientSession
-     * @param trans The transport to use for OBEX transactions
-     * @param supportsSrm True if Single Response Mode should be used e.g. if the
-     *        supplied transport is a TCP or l2cap channel.
-     * @throws IOException if it occurs while opening the transport streams.
-     */
-    public ClientSession(final ObexTransport trans, final boolean supportsSrm) throws IOException {
-        mInput = trans.openInputStream();
-        mOutput = trans.openOutputStream();
-        mOpen = true;
-        mRequestActive = false;
-        mLocalSrmSupported = supportsSrm;
-        mTransport = trans;
-    }
-
-    public HeaderSet connect(final HeaderSet header) throws IOException {
-        ensureOpen();
-        if (mObexConnected) {
-            throw new IOException("Already connected to server");
-        }
-        setRequestActive();
-
-        int totalLength = 4;
-        byte[] head = null;
-
-        // Determine the header byte array
-        if (header != null) {
-            if (header.nonce != null) {
-                mChallengeDigest = new byte[16];
-                System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
-            }
-            head = ObexHelper.createHeader(header, false);
-            totalLength += head.length;
-        }
-        /*
-        * Write the OBEX CONNECT packet to the server.
-        * Byte 0: 0x80
-        * Byte 1&2: Connect Packet Length
-        * Byte 3: OBEX Version Number (Presently, 0x10)
-        * Byte 4: Flags (For TCP 0x00)
-        * Byte 5&6: Max OBEX Packet Length (Defined in MAX_PACKET_SIZE)
-        * Byte 7 to n: headers
-        */
-        byte[] requestPacket = new byte[totalLength];
-        int maxRxPacketSize = ObexHelper.getMaxRxPacketSize(mTransport);
-        // We just need to start at  byte 3 since the sendRequest() method will
-        // handle the length and 0x80.
-        requestPacket[0] = (byte)0x10;
-        requestPacket[1] = (byte)0x00;
-        requestPacket[2] = (byte)(maxRxPacketSize >> 8);
-        requestPacket[3] = (byte)(maxRxPacketSize & 0xFF);
-        if (head != null) {
-            System.arraycopy(head, 0, requestPacket, 4, head.length);
-        }
-
-        // Since we are not yet connected, the peer max packet size is unknown,
-        // hence we are only guaranteed the server will use the first 7 bytes.
-        if ((requestPacket.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) {
-            throw new IOException("Packet size exceeds max packet size for connect");
-        }
-
-        HeaderSet returnHeaderSet = new HeaderSet();
-        sendRequest(ObexHelper.OBEX_OPCODE_CONNECT, requestPacket, returnHeaderSet, null, false);
-
-        /*
-        * Read the response from the OBEX server.
-        * Byte 0: Response Code (If successful then OBEX_HTTP_OK)
-        * Byte 1&2: Packet Length
-        * Byte 3: OBEX Version Number
-        * Byte 4: Flags3
-        * Byte 5&6: Max OBEX packet Length
-        * Byte 7 to n: Optional HeaderSet
-        */
-        if (returnHeaderSet.responseCode == ResponseCodes.OBEX_HTTP_OK) {
-            mObexConnected = true;
-        }
-        setRequestInactive();
-
-        return returnHeaderSet;
-    }
-
-    public Operation get(HeaderSet header) throws IOException {
-
-        if (!mObexConnected) {
-            throw new IOException("Not connected to the server");
-        }
-        setRequestActive();
-
-        ensureOpen();
-
-        HeaderSet head;
-        if (header == null) {
-            head = new HeaderSet();
-        } else {
-            head = header;
-            if (head.nonce != null) {
-                mChallengeDigest = new byte[16];
-                System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
-            }
-        }
-        // Add the connection ID if one exists
-        if (mConnectionId != null) {
-            head.mConnectionID = new byte[4];
-            System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
-        }
-
-        if(mLocalSrmSupported) {
-            head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, ObexHelper.OBEX_SRM_ENABLE);
-            /* TODO: Consider creating an interface to get the wait state.
-             * On an android system, I cannot see when this is to be used.
-             * except perhaps if we are to wait for user accept on a push message.
-            if(getLocalWaitState()) {
-                head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, ObexHelper.OBEX_SRMP_WAIT);
-            }
-            */
-        }
-
-        return new ClientOperation(mMaxTxPacketSize, this, head, true);
-    }
-
-    /**
-     * 0xCB Connection Id an identifier used for OBEX connection multiplexing
-     */
-    public void setConnectionID(long id) {
-        if ((id < 0) || (id > 0xFFFFFFFFL)) {
-            throw new IllegalArgumentException("Connection ID is not in a valid range");
-        }
-        mConnectionId = ObexHelper.convertToByteArray(id);
-    }
-
-    public HeaderSet delete(HeaderSet header) throws IOException {
-
-        Operation op = put(header);
-        op.getResponseCode();
-        HeaderSet returnValue = op.getReceivedHeader();
-        op.close();
-
-        return returnValue;
-    }
-
-    public HeaderSet disconnect(HeaderSet header) throws IOException {
-        if (!mObexConnected) {
-            throw new IOException("Not connected to the server");
-        }
-        setRequestActive();
-
-        ensureOpen();
-        // Determine the header byte array
-        byte[] head = null;
-        if (header != null) {
-            if (header.nonce != null) {
-                mChallengeDigest = new byte[16];
-                System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
-            }
-            // Add the connection ID if one exists
-            if (mConnectionId != null) {
-                header.mConnectionID = new byte[4];
-                System.arraycopy(mConnectionId, 0, header.mConnectionID, 0, 4);
-            }
-            head = ObexHelper.createHeader(header, false);
-
-            if ((head.length + 3) > mMaxTxPacketSize) {
-                throw new IOException("Packet size exceeds max packet size");
-            }
-        } else {
-            // Add the connection ID if one exists
-            if (mConnectionId != null) {
-                head = new byte[5];
-                head[0] = (byte)HeaderSet.CONNECTION_ID;
-                System.arraycopy(mConnectionId, 0, head, 1, 4);
-            }
-        }
-
-        HeaderSet returnHeaderSet = new HeaderSet();
-        sendRequest(ObexHelper.OBEX_OPCODE_DISCONNECT, head, returnHeaderSet, null, false);
-
-        /*
-         * An OBEX DISCONNECT reply from the server:
-         * Byte 1: Response code
-         * Bytes 2 & 3: packet size
-         * Bytes 4 & up: headers
-         */
-
-        /* response code , and header are ignored
-         * */
-
-        synchronized (this) {
-            mObexConnected = false;
-            setRequestInactive();
-        }
-
-        return returnHeaderSet;
-    }
-
-    public long getConnectionID() {
-
-        if (mConnectionId == null) {
-            return -1;
-        }
-        return ObexHelper.convertToLong(mConnectionId);
-    }
-
-    public Operation put(HeaderSet header) throws IOException {
-        if (!mObexConnected) {
-            throw new IOException("Not connected to the server");
-        }
-        setRequestActive();
-
-        ensureOpen();
-        HeaderSet head;
-        if (header == null) {
-            head = new HeaderSet();
-        } else {
-            head = header;
-            // when auth is initiated by client ,save the digest
-            if (head.nonce != null) {
-                mChallengeDigest = new byte[16];
-                System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
-            }
-        }
-
-        // Add the connection ID if one exists
-        if (mConnectionId != null) {
-
-            head.mConnectionID = new byte[4];
-            System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
-        }
-
-        if(mLocalSrmSupported) {
-            head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, ObexHelper.OBEX_SRM_ENABLE);
-            /* TODO: Consider creating an interface to get the wait state.
-             * On an android system, I cannot see when this is to be used.
-            if(getLocalWaitState()) {
-                head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, ObexHelper.OBEX_SRMP_WAIT);
-            }
-             */
-        }
-        return new ClientOperation(mMaxTxPacketSize, this, head, false);
-    }
-
-    public void setAuthenticator(Authenticator auth) throws IOException {
-        if (auth == null) {
-            throw new IOException("Authenticator may not be null");
-        }
-        mAuthenticator = auth;
-    }
-
-    public HeaderSet setPath(HeaderSet header, boolean backup, boolean create) throws IOException {
-        if (!mObexConnected) {
-            throw new IOException("Not connected to the server");
-        }
-        setRequestActive();
-        ensureOpen();
-
-        int totalLength = 2;
-        byte[] head = null;
-        HeaderSet headset;
-        if (header == null) {
-            headset = new HeaderSet();
-        } else {
-            headset = header;
-            if (headset.nonce != null) {
-                mChallengeDigest = new byte[16];
-                System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
-            }
-        }
-
-        // when auth is initiated by client ,save the digest
-        if (headset.nonce != null) {
-            mChallengeDigest = new byte[16];
-            System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
-        }
-
-        // Add the connection ID if one exists
-        if (mConnectionId != null) {
-            headset.mConnectionID = new byte[4];
-            System.arraycopy(mConnectionId, 0, headset.mConnectionID, 0, 4);
-        }
-
-        head = ObexHelper.createHeader(headset, false);
-        totalLength += head.length;
-
-        if (totalLength > mMaxTxPacketSize) {
-            throw new IOException("Packet size exceeds max packet size");
-        }
-
-        int flags = 0;
-        /*
-         * The backup flag bit is bit 0 so if we add 1, this will set that bit
-         */
-        if (backup) {
-            flags++;
-        }
-        /*
-         * The create bit is bit 1 so if we or with 2 the bit will be set.
-         */
-        if (!create) {
-            flags |= 2;
-        }
-
-        /*
-         * An OBEX SETPATH packet to the server:
-         * Byte 1: 0x85
-         * Byte 2 & 3: packet size
-         * Byte 4: flags
-         * Byte 5: constants
-         * Byte 6 & up: headers
-         */
-        byte[] packet = new byte[totalLength];
-        packet[0] = (byte)flags;
-        packet[1] = (byte)0x00;
-        if (headset != null) {
-            System.arraycopy(head, 0, packet, 2, head.length);
-        }
-
-        HeaderSet returnHeaderSet = new HeaderSet();
-        sendRequest(ObexHelper.OBEX_OPCODE_SETPATH, packet, returnHeaderSet, null, false);
-
-        /*
-         * An OBEX SETPATH reply from the server:
-         * Byte 1: Response code
-         * Bytes 2 & 3: packet size
-         * Bytes 4 & up: headers
-         */
-
-        setRequestInactive();
-
-        return returnHeaderSet;
-    }
-
-    /**
-     * Verifies that the connection is open.
-     * @throws IOException if the connection is closed
-     */
-    public synchronized void ensureOpen() throws IOException {
-        if (!mOpen) {
-            throw new IOException("Connection closed");
-        }
-    }
-
-    /**
-     * Set request inactive. Allows Put and get operation objects to tell this
-     * object when they are done.
-     */
-    /*package*/synchronized void setRequestInactive() {
-        mRequestActive = false;
-    }
-
-    /**
-     * Set request to active.
-     * @throws IOException if already active
-     */
-    private synchronized void setRequestActive() throws IOException {
-        if (mRequestActive) {
-            throw new IOException("OBEX request is already being performed");
-        }
-        mRequestActive = true;
-    }
-
-    /**
-     * Sends a standard request to the client. It will then wait for the reply
-     * and update the header set object provided. If any authentication headers
-     * (i.e. authentication challenge or authentication response) are received,
-     * they will be processed.
-     * @param opCode the type of request to send to the client
-     * @param head the headers to send to the client
-     * @param header the header object to update with the response
-     * @param privateInput the input stream used by the Operation object; null
-     *        if this is called on a CONNECT, SETPATH or DISCONNECT
-     * @return
-     *        <code>true</code> if the operation completed successfully;
-     *        <code>false</code> if an authentication response failed to pass
-     * @throws IOException if an IO error occurs
-     */
-    public boolean sendRequest(int opCode, byte[] head, HeaderSet header,
-            PrivateInputStream privateInput, boolean srmActive) throws IOException {
-        //check header length with local max size
-        if (head != null) {
-            if ((head.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) {
-                // TODO: This is an implementation limit - not a specification requirement.
-                throw new IOException("header too large ");
-            }
-        }
-
-        boolean skipSend = false;
-        boolean skipReceive = false;
-        if (srmActive == true) {
-            if (opCode == ObexHelper.OBEX_OPCODE_PUT) {
-                // we are in the middle of a SRM PUT operation, don't expect a continue.
-                skipReceive = true;
-            } else if (opCode == ObexHelper.OBEX_OPCODE_GET) {
-                // We are still sending the get request, send, but don't expect continue
-                // until the request is transfered (the final bit is set)
-                skipReceive = true;
-            } else if (opCode == ObexHelper.OBEX_OPCODE_GET_FINAL) {
-                // All done sending the request, expect data from the server, without
-                // sending continue.
-                skipSend = true;
-            }
-
-        }
-
-        int bytesReceived;
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        out.write((byte)opCode);
-
-        // Determine if there are any headers to send
-        if (head == null) {
-            out.write(0x00);
-            out.write(0x03);
-        } else {
-            out.write((byte)((head.length + 3) >> 8));
-            out.write((byte)(head.length + 3));
-            out.write(head);
-        }
-
-        if (!skipSend) {
-            // Write the request to the output stream and flush the stream
-            mOutput.write(out.toByteArray());
-            // TODO: is this really needed? if this flush is implemented
-            //       correctly, we will get a gap between each obex packet.
-            //       which is kind of the idea behind SRM to avoid.
-            //  Consider offloading to another thread (async action)
-            mOutput.flush();
-        }
-
-        if (!skipReceive) {
-            header.responseCode = mInput.read();
-
-            int length = ((mInput.read() << 8) | (mInput.read()));
-
-            if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
-                throw new IOException("Packet received exceeds packet size limit");
-            }
-            if (length > ObexHelper.BASE_PACKET_LENGTH) {
-                byte[] data = null;
-                if (opCode == ObexHelper.OBEX_OPCODE_CONNECT) {
-                    @SuppressWarnings("unused")
-                    int version = mInput.read();
-                    @SuppressWarnings("unused")
-                    int flags = mInput.read();
-                    mMaxTxPacketSize = (mInput.read() << 8) + mInput.read();
-
-                    //check with local max size
-                    if (mMaxTxPacketSize > ObexHelper.MAX_CLIENT_PACKET_SIZE) {
-                        mMaxTxPacketSize = ObexHelper.MAX_CLIENT_PACKET_SIZE;
-                    }
-
-                    // check with transport maximum size
-                    if(mMaxTxPacketSize > ObexHelper.getMaxTxPacketSize(mTransport)) {
-                        // To increase this size, increase the buffer size in L2CAP layer
-                        // in Bluedroid.
-                        Log.w(TAG, "An OBEX packet size of " + mMaxTxPacketSize + "was"
-                                + " requested. Transport only allows: "
-                                + ObexHelper.getMaxTxPacketSize(mTransport)
-                                + " Lowering limit to this value.");
-                        mMaxTxPacketSize = ObexHelper.getMaxTxPacketSize(mTransport);
-                    }
-
-                    if (length > 7) {
-                        data = new byte[length - 7];
-
-                        bytesReceived = mInput.read(data);
-                        while (bytesReceived != (length - 7)) {
-                            bytesReceived += mInput.read(data, bytesReceived, data.length
-                                    - bytesReceived);
-                        }
-                    } else {
-                        return true;
-                    }
-                } else {
-                    data = new byte[length - 3];
-                    bytesReceived = mInput.read(data);
-
-                    while (bytesReceived != (length - 3)) {
-                        bytesReceived += mInput.read(data, bytesReceived, data.length - bytesReceived);
-                    }
-                    if (opCode == ObexHelper.OBEX_OPCODE_ABORT) {
-                        return true;
-                    }
-                }
-
-                byte[] body = ObexHelper.updateHeaderSet(header, data);
-                if ((privateInput != null) && (body != null)) {
-                    privateInput.writeBytes(body, 1);
-                }
-
-                if (header.mConnectionID != null) {
-                    mConnectionId = new byte[4];
-                    System.arraycopy(header.mConnectionID, 0, mConnectionId, 0, 4);
-                }
-
-                if (header.mAuthResp != null) {
-                    if (!handleAuthResp(header.mAuthResp)) {
-                        setRequestInactive();
-                        throw new IOException("Authentication Failed");
-                    }
-                }
-
-                if ((header.responseCode == ResponseCodes.OBEX_HTTP_UNAUTHORIZED)
-                        && (header.mAuthChall != null)) {
-
-                    if (handleAuthChall(header)) {
-                        out.write((byte)HeaderSet.AUTH_RESPONSE);
-                        out.write((byte)((header.mAuthResp.length + 3) >> 8));
-                        out.write((byte)(header.mAuthResp.length + 3));
-                        out.write(header.mAuthResp);
-                        header.mAuthChall = null;
-                        header.mAuthResp = null;
-
-                        byte[] sendHeaders = new byte[out.size() - 3];
-                        System.arraycopy(out.toByteArray(), 3, sendHeaders, 0, sendHeaders.length);
-
-                        return sendRequest(opCode, sendHeaders, header, privateInput, false);
-                    }
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public void close() throws IOException {
-        mOpen = false;
-        mInput.close();
-        mOutput.close();
-    }
-
-    public boolean isSrmSupported() {
-        return mLocalSrmSupported;
-    }
-}
diff --git a/obex/javax/obex/HeaderSet.java b/obex/javax/obex/HeaderSet.java
deleted file mode 100644
index 35fe186..0000000
--- a/obex/javax/obex/HeaderSet.java
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Copyright (c) 2014 The Android Open Source Project
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Calendar;
-import java.security.SecureRandom;
-
-/**
- * This class implements the javax.obex.HeaderSet interface for OBEX over
- * RFCOMM or OBEX over l2cap.
- * @hide
- */
-public final class HeaderSet {
-
-    /**
-     * Represents the OBEX Count header. This allows the connection statement to
-     * tell the server how many objects it plans to send or retrieve.
-     * <P>
-     * The value of <code>COUNT</code> is 0xC0 (192).
-     */
-    public static final int COUNT = 0xC0;
-
-    /**
-     * Represents the OBEX Name header. This specifies the name of the object.
-     * <P>
-     * The value of <code>NAME</code> is 0x01 (1).
-     */
-    public static final int NAME = 0x01;
-
-    /**
-     * Represents the OBEX Type header. This allows a request to specify the
-     * type of the object (e.g. text, html, binary, etc.).
-     * <P>
-     * The value of <code>TYPE</code> is 0x42 (66).
-     */
-    public static final int TYPE = 0x42;
-
-    /**
-     * Represents the OBEX Length header. This is the length of the object in
-     * bytes.
-     * <P>
-     * The value of <code>LENGTH</code> is 0xC3 (195).
-     */
-    public static final int LENGTH = 0xC3;
-
-    /**
-     * Represents the OBEX Time header using the ISO 8601 standards. This is the
-     * preferred time header.
-     * <P>
-     * The value of <code>TIME_ISO_8601</code> is 0x44 (68).
-     */
-    public static final int TIME_ISO_8601 = 0x44;
-
-    /**
-     * Represents the OBEX Time header using the 4 byte representation. This is
-     * only included for backwards compatibility. It represents the number of
-     * seconds since January 1, 1970.
-     * <P>
-     * The value of <code>TIME_4_BYTE</code> is 0xC4 (196).
-     */
-    public static final int TIME_4_BYTE = 0xC4;
-
-    /**
-     * Represents the OBEX Description header. This is a text description of the
-     * object.
-     * <P>
-     * The value of <code>DESCRIPTION</code> is 0x05 (5).
-     */
-    public static final int DESCRIPTION = 0x05;
-
-    /**
-     * Represents the OBEX Target header. This is the name of the service an
-     * operation is targeted to.
-     * <P>
-     * The value of <code>TARGET</code> is 0x46 (70).
-     */
-    public static final int TARGET = 0x46;
-
-    /**
-     * Represents the OBEX HTTP header. This allows an HTTP 1.X header to be
-     * included in a request or reply.
-     * <P>
-     * The value of <code>HTTP</code> is 0x47 (71).
-     */
-    public static final int HTTP = 0x47;
-
-    /**
-     * Represents the OBEX BODY header.
-     * <P>
-     * The value of <code>BODY</code> is 0x48 (72).
-     */
-    public static final int BODY = 0x48;
-
-    /**
-     * Represents the OBEX End of BODY header.
-     * <P>
-     * The value of <code>BODY</code> is 0x49 (73).
-     */
-    public static final int END_OF_BODY = 0x49;
-
-    /**
-     * Represents the OBEX Who header. Identifies the OBEX application to
-     * determine if the two peers are talking to each other.
-     * <P>
-     * The value of <code>WHO</code> is 0x4A (74).
-     */
-    public static final int WHO = 0x4A;
-
-    /**
-     * Represents the OBEX Connection ID header. Identifies used for OBEX
-     * connection multiplexing.
-     * <P>
-     * The value of <code>CONNECTION_ID</code> is 0xCB (203).
-     */
-
-    public static final int CONNECTION_ID = 0xCB;
-
-    /**
-     * Represents the OBEX Application Parameter header. This header specifies
-     * additional application request and response information.
-     * <P>
-     * The value of <code>APPLICATION_PARAMETER</code> is 0x4C (76).
-     */
-    public static final int APPLICATION_PARAMETER = 0x4C;
-
-    /**
-     * Represents the OBEX authentication digest-challenge.
-     * <P>
-     * The value of <code>AUTH_CHALLENGE</code> is 0x4D (77).
-     */
-    public static final int AUTH_CHALLENGE = 0x4D;
-
-    /**
-     * Represents the OBEX authentication digest-response.
-     * <P>
-     * The value of <code>AUTH_RESPONSE</code> is 0x4E (78).
-     */
-    public static final int AUTH_RESPONSE = 0x4E;
-
-    /**
-     * Represents the OBEX Object Class header. This header specifies the OBEX
-     * object class of the object.
-     * <P>
-     * The value of <code>OBJECT_CLASS</code> is 0x4F (79).
-     */
-    public static final int OBJECT_CLASS = 0x4F;
-
-    /**
-     * Represents the OBEX Single Response Mode (SRM). This header is used
-     * for Single response mode, introduced in OBEX 1.5.
-     * <P>
-     * The value of <code>SINGLE_RESPONSE_MODE</code> is 0x97 (151).
-     */
-    public static final int SINGLE_RESPONSE_MODE = 0x97;
-
-    /**
-     * Represents the OBEX Single Response Mode Parameters. This header is used
-     * for Single response mode, introduced in OBEX 1.5.
-     * <P>
-     * The value of <code>SINGLE_RESPONSE_MODE_PARAMETER</code> is 0x98 (152).
-     */
-    public static final int SINGLE_RESPONSE_MODE_PARAMETER = 0x98;
-
-    private Long mCount; // 4 byte unsigned integer
-
-    private String mName; // null terminated Unicode text string
-
-    private boolean mEmptyName;
-
-    private String mType; // null terminated ASCII text string
-
-    private Long mLength; // 4 byte unsigend integer
-
-    private Calendar mIsoTime; // String of the form YYYYMMDDTHHMMSSZ
-
-    private Calendar mByteTime; // 4 byte unsigned integer
-
-    private String mDescription; // null terminated Unicode text String
-
-    private byte[] mTarget; // byte sequence
-
-    private byte[] mHttpHeader; // byte sequence
-
-    private byte[] mWho; // length prefixed byte sequence
-
-    private byte[] mAppParam; // byte sequence of the form tag length value
-
-    private byte[] mObjectClass; // byte sequence
-
-    private String[] mUnicodeUserDefined; // null terminated unicode string
-
-    private byte[][] mSequenceUserDefined; // byte sequence user defined
-
-    private Byte[] mByteUserDefined; // 1 byte
-
-    private Long[] mIntegerUserDefined; // 4 byte unsigned integer
-
-    private SecureRandom mRandom = null;
-
-    private Byte mSingleResponseMode; // byte to indicate enable/disable/support for SRM
-
-    private Byte mSrmParam; // byte representing the SRM parameters - only "wait"
-                            // is supported by Bluetooth
-
-    /*package*/ byte[] nonce;
-
-    public byte[] mAuthChall; // The authentication challenge header
-
-    public byte[] mAuthResp; // The authentication response header
-
-    public byte[] mConnectionID; // THe connection ID
-
-    public int responseCode;
-
-    /**
-     * Creates new <code>HeaderSet</code> object.
-     * @param size the max packet size for this connection
-     */
-    public HeaderSet() {
-        mUnicodeUserDefined = new String[16];
-        mSequenceUserDefined = new byte[16][];
-        mByteUserDefined = new Byte[16];
-        mIntegerUserDefined = new Long[16];
-        responseCode = -1;
-    }
-
-    /**
-     * Sets flag for special "value" of NAME header which should be empty. This
-     * is not the same as NAME header with empty string in which case it will
-     * have length of 5 bytes. It should be 3 bytes with only header id and
-     * length field.
-     */
-    public void setEmptyNameHeader() {
-        mName = null;
-        mEmptyName = true;
-    }
-
-    /**
-     * Gets flag for special "value" of NAME header which should be empty. See
-     * above.
-     */
-    public boolean getEmptyNameHeader() {
-        return mEmptyName;
-    }
-
-    /**
-     * Sets the value of the header identifier to the value provided. The type
-     * of object must correspond to the Java type defined in the description of
-     * this interface. If <code>null</code> is passed as the
-     * <code>headerValue</code> then the header will be removed from the set of
-     * headers to include in the next request.
-     * @param headerID the identifier to include in the message
-     * @param headerValue the value of the header identifier
-     * @throws IllegalArgumentException if the header identifier provided is not
-     *         one defined in this interface or a user-defined header; if the
-     *         type of <code>headerValue</code> is not the correct Java type as
-     *         defined in the description of this interface\
-     */
-    public void setHeader(int headerID, Object headerValue) {
-        long temp = -1;
-
-        switch (headerID) {
-            case COUNT:
-                if (!(headerValue instanceof Long)) {
-                    if (headerValue == null) {
-                        mCount = null;
-                        break;
-                    }
-                    throw new IllegalArgumentException("Count must be a Long");
-                }
-                temp = ((Long)headerValue).longValue();
-                if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
-                    throw new IllegalArgumentException("Count must be between 0 and 0xFFFFFFFF");
-                }
-                mCount = (Long)headerValue;
-                break;
-            case NAME:
-                if ((headerValue != null) && (!(headerValue instanceof String))) {
-                    throw new IllegalArgumentException("Name must be a String");
-                }
-                mEmptyName = false;
-                mName = (String)headerValue;
-                break;
-            case TYPE:
-                if ((headerValue != null) && (!(headerValue instanceof String))) {
-                    throw new IllegalArgumentException("Type must be a String");
-                }
-                mType = (String)headerValue;
-                break;
-            case LENGTH:
-                if (!(headerValue instanceof Long)) {
-                    if (headerValue == null) {
-                        mLength = null;
-                        break;
-                    }
-                    throw new IllegalArgumentException("Length must be a Long");
-                }
-                temp = ((Long)headerValue).longValue();
-                if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
-                    throw new IllegalArgumentException("Length must be between 0 and 0xFFFFFFFF");
-                }
-                mLength = (Long)headerValue;
-                break;
-            case TIME_ISO_8601:
-                if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
-                    throw new IllegalArgumentException("Time ISO 8601 must be a Calendar");
-                }
-                mIsoTime = (Calendar)headerValue;
-                break;
-            case TIME_4_BYTE:
-                if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
-                    throw new IllegalArgumentException("Time 4 Byte must be a Calendar");
-                }
-                mByteTime = (Calendar)headerValue;
-                break;
-            case DESCRIPTION:
-                if ((headerValue != null) && (!(headerValue instanceof String))) {
-                    throw new IllegalArgumentException("Description must be a String");
-                }
-                mDescription = (String)headerValue;
-                break;
-            case TARGET:
-                if (headerValue == null) {
-                    mTarget = null;
-                } else {
-                    if (!(headerValue instanceof byte[])) {
-                        throw new IllegalArgumentException("Target must be a byte array");
-                    } else {
-                        mTarget = new byte[((byte[])headerValue).length];
-                        System.arraycopy(headerValue, 0, mTarget, 0, mTarget.length);
-                    }
-                }
-                break;
-            case HTTP:
-                if (headerValue == null) {
-                    mHttpHeader = null;
-                } else {
-                    if (!(headerValue instanceof byte[])) {
-                        throw new IllegalArgumentException("HTTP must be a byte array");
-                    } else {
-                        mHttpHeader = new byte[((byte[])headerValue).length];
-                        System.arraycopy(headerValue, 0, mHttpHeader, 0, mHttpHeader.length);
-                    }
-                }
-                break;
-            case WHO:
-                if (headerValue == null) {
-                    mWho = null;
-                } else {
-                    if (!(headerValue instanceof byte[])) {
-                        throw new IllegalArgumentException("WHO must be a byte array");
-                    } else {
-                        mWho = new byte[((byte[])headerValue).length];
-                        System.arraycopy(headerValue, 0, mWho, 0, mWho.length);
-                    }
-                }
-                break;
-            case OBJECT_CLASS:
-                if (headerValue == null) {
-                    mObjectClass = null;
-                } else {
-                    if (!(headerValue instanceof byte[])) {
-                        throw new IllegalArgumentException("Object Class must be a byte array");
-                    } else {
-                        mObjectClass = new byte[((byte[])headerValue).length];
-                        System.arraycopy(headerValue, 0, mObjectClass, 0, mObjectClass.length);
-                    }
-                }
-                break;
-            case APPLICATION_PARAMETER:
-                if (headerValue == null) {
-                    mAppParam = null;
-                } else {
-                    if (!(headerValue instanceof byte[])) {
-                        throw new IllegalArgumentException(
-                                "Application Parameter must be a byte array");
-                    } else {
-                        mAppParam = new byte[((byte[])headerValue).length];
-                        System.arraycopy(headerValue, 0, mAppParam, 0, mAppParam.length);
-                    }
-                }
-                break;
-            case SINGLE_RESPONSE_MODE:
-                if (headerValue == null) {
-                    mSingleResponseMode = null;
-                } else {
-                    if (!(headerValue instanceof Byte)) {
-                        throw new IllegalArgumentException(
-                                "Single Response Mode must be a Byte");
-                    } else {
-                        mSingleResponseMode = (Byte)headerValue;
-                    }
-                }
-                break;
-            case SINGLE_RESPONSE_MODE_PARAMETER:
-                if (headerValue == null) {
-                    mSrmParam = null;
-                } else {
-                    if (!(headerValue instanceof Byte)) {
-                        throw new IllegalArgumentException(
-                                "Single Response Mode Parameter must be a Byte");
-                    } else {
-                        mSrmParam = (Byte)headerValue;
-                    }
-                }
-                break;
-            default:
-                // Verify that it was not a Unicode String user Defined
-                if ((headerID >= 0x30) && (headerID <= 0x3F)) {
-                    if ((headerValue != null) && (!(headerValue instanceof String))) {
-                        throw new IllegalArgumentException(
-                                "Unicode String User Defined must be a String");
-                    }
-                    mUnicodeUserDefined[headerID - 0x30] = (String)headerValue;
-
-                    break;
-                }
-                // Verify that it was not a byte sequence user defined value
-                if ((headerID >= 0x70) && (headerID <= 0x7F)) {
-
-                    if (headerValue == null) {
-                        mSequenceUserDefined[headerID - 0x70] = null;
-                    } else {
-                        if (!(headerValue instanceof byte[])) {
-                            throw new IllegalArgumentException(
-                                    "Byte Sequence User Defined must be a byte array");
-                        } else {
-                            mSequenceUserDefined[headerID - 0x70] = new byte[((byte[])headerValue).length];
-                            System.arraycopy(headerValue, 0, mSequenceUserDefined[headerID - 0x70],
-                                    0, mSequenceUserDefined[headerID - 0x70].length);
-                        }
-                    }
-                    break;
-                }
-                // Verify that it was not a Byte user Defined
-                if ((headerID >= 0xB0) && (headerID <= 0xBF)) {
-                    if ((headerValue != null) && (!(headerValue instanceof Byte))) {
-                        throw new IllegalArgumentException("ByteUser Defined must be a Byte");
-                    }
-                    mByteUserDefined[headerID - 0xB0] = (Byte)headerValue;
-
-                    break;
-                }
-                // Verify that is was not the 4 byte unsigned integer user
-                // defined header
-                if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
-                    if (!(headerValue instanceof Long)) {
-                        if (headerValue == null) {
-                            mIntegerUserDefined[headerID - 0xF0] = null;
-                            break;
-                        }
-                        throw new IllegalArgumentException("Integer User Defined must be a Long");
-                    }
-                    temp = ((Long)headerValue).longValue();
-                    if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
-                        throw new IllegalArgumentException(
-                                "Integer User Defined must be between 0 and 0xFFFFFFFF");
-                    }
-                    mIntegerUserDefined[headerID - 0xF0] = (Long)headerValue;
-                    break;
-                }
-                throw new IllegalArgumentException("Invalid Header Identifier");
-        }
-    }
-
-    /**
-     * Retrieves the value of the header identifier provided. The type of the
-     * Object returned is defined in the description of this interface.
-     * @param headerID the header identifier whose value is to be returned
-     * @return the value of the header provided or <code>null</code> if the
-     *         header identifier specified is not part of this
-     *         <code>HeaderSet</code> object
-     * @throws IllegalArgumentException if the <code>headerID</code> is not one
-     *         defined in this interface or any of the user-defined headers
-     * @throws IOException if an error occurred in the transport layer during
-     *         the operation or if the connection has been closed
-     */
-    public Object getHeader(int headerID) throws IOException {
-
-        switch (headerID) {
-            case COUNT:
-                return mCount;
-            case NAME:
-                return mName;
-            case TYPE:
-                return mType;
-            case LENGTH:
-                return mLength;
-            case TIME_ISO_8601:
-                return mIsoTime;
-            case TIME_4_BYTE:
-                return mByteTime;
-            case DESCRIPTION:
-                return mDescription;
-            case TARGET:
-                return mTarget;
-            case HTTP:
-                return mHttpHeader;
-            case WHO:
-                return mWho;
-            case CONNECTION_ID:
-                return mConnectionID;
-            case OBJECT_CLASS:
-                return mObjectClass;
-            case APPLICATION_PARAMETER:
-                return mAppParam;
-            case SINGLE_RESPONSE_MODE:
-                return mSingleResponseMode;
-            case SINGLE_RESPONSE_MODE_PARAMETER:
-                return mSrmParam;
-            default:
-                // Verify that it was not a Unicode String user Defined
-                if ((headerID >= 0x30) && (headerID <= 0x3F)) {
-                    return mUnicodeUserDefined[headerID - 0x30];
-                }
-                // Verify that it was not a byte sequence user defined header
-                if ((headerID >= 0x70) && (headerID <= 0x7F)) {
-                    return mSequenceUserDefined[headerID - 0x70];
-                }
-                // Verify that it was not a byte user defined header
-                if ((headerID >= 0xB0) && (headerID <= 0xBF)) {
-                    return mByteUserDefined[headerID - 0xB0];
-                }
-                // Verify that it was not a integer user defined header
-                if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
-                    return mIntegerUserDefined[headerID - 0xF0];
-                }
-                throw new IllegalArgumentException("Invalid Header Identifier");
-        }
-    }
-
-    /**
-     * Retrieves the list of headers that may be retrieved via the
-     * <code>getHeader</code> method that will not return <code>null</code>. In
-     * other words, this method returns all the headers that are available in
-     * this object.
-     * @see #getHeader
-     * @return the array of headers that are set in this object or
-     *         <code>null</code> if no headers are available
-     * @throws IOException if an error occurred in the transport layer during
-     *         the operation or the connection has been closed
-     */
-    public int[] getHeaderList() throws IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-
-        if (mCount != null) {
-            out.write(COUNT);
-        }
-        if (mName != null) {
-            out.write(NAME);
-        }
-        if (mType != null) {
-            out.write(TYPE);
-        }
-        if (mLength != null) {
-            out.write(LENGTH);
-        }
-        if (mIsoTime != null) {
-            out.write(TIME_ISO_8601);
-        }
-        if (mByteTime != null) {
-            out.write(TIME_4_BYTE);
-        }
-        if (mDescription != null) {
-            out.write(DESCRIPTION);
-        }
-        if (mTarget != null) {
-            out.write(TARGET);
-        }
-        if (mHttpHeader != null) {
-            out.write(HTTP);
-        }
-        if (mWho != null) {
-            out.write(WHO);
-        }
-        if (mAppParam != null) {
-            out.write(APPLICATION_PARAMETER);
-        }
-        if (mObjectClass != null) {
-            out.write(OBJECT_CLASS);
-        }
-        if(mSingleResponseMode != null) {
-            out.write(SINGLE_RESPONSE_MODE);
-        }
-        if(mSrmParam != null) {
-            out.write(SINGLE_RESPONSE_MODE_PARAMETER);
-        }
-
-        for (int i = 0x30; i < 0x40; i++) {
-            if (mUnicodeUserDefined[i - 0x30] != null) {
-                out.write(i);
-            }
-        }
-
-        for (int i = 0x70; i < 0x80; i++) {
-            if (mSequenceUserDefined[i - 0x70] != null) {
-                out.write(i);
-            }
-        }
-
-        for (int i = 0xB0; i < 0xC0; i++) {
-            if (mByteUserDefined[i - 0xB0] != null) {
-                out.write(i);
-            }
-        }
-
-        for (int i = 0xF0; i < 0x100; i++) {
-            if (mIntegerUserDefined[i - 0xF0] != null) {
-                out.write(i);
-            }
-        }
-
-        byte[] headers = out.toByteArray();
-        out.close();
-
-        if ((headers == null) || (headers.length == 0)) {
-            return null;
-        }
-
-        int[] result = new int[headers.length];
-        for (int i = 0; i < headers.length; i++) {
-            // Convert the byte to a positive integer.  That is, an integer
-            // between 0 and 256.
-            result[i] = headers[i] & 0xFF;
-        }
-
-        return result;
-    }
-
-    /**
-     * Sets the authentication challenge header. The <code>realm</code> will be
-     * encoded based upon the default encoding scheme used by the implementation
-     * to encode strings. Therefore, the encoding scheme used to encode the
-     * <code>realm</code> is application dependent.
-     * @param realm a short description that describes what password to use; if
-     *        <code>null</code> no realm will be sent in the authentication
-     *        challenge header
-     * @param userID if <code>true</code>, a user ID is required in the reply;
-     *        if <code>false</code>, no user ID is required
-     * @param access if <code>true</code> then full access will be granted if
-     *        successful; if <code>false</code> then read-only access will be
-     *        granted if successful
-     * @throws IOException
-     */
-    public void createAuthenticationChallenge(String realm, boolean userID, boolean access)
-            throws IOException {
-
-        nonce = new byte[16];
-        if(mRandom == null) {
-            mRandom = new SecureRandom();
-        }
-        for (int i = 0; i < 16; i++) {
-            nonce[i] = (byte)mRandom.nextInt();
-        }
-
-        mAuthChall = ObexHelper.computeAuthenticationChallenge(nonce, realm, access, userID);
-    }
-
-    /**
-     * Returns the response code received from the server. Response codes are
-     * defined in the <code>ResponseCodes</code> class.
-     * @see ResponseCodes
-     * @return the response code retrieved from the server
-     * @throws IOException if an error occurred in the transport layer during
-     *         the transaction; if this method is called on a
-     *         <code>HeaderSet</code> object created by calling
-     *         <code>createHeaderSet()</code> in a <code>ClientSession</code>
-     *         object; if this object was created by an OBEX server
-     */
-    public int getResponseCode() throws IOException {
-        if (responseCode == -1) {
-            throw new IOException("May not be called on a server");
-        } else {
-            return responseCode;
-        }
-    }
-}
diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java
deleted file mode 100644
index 843793a..0000000
--- a/obex/javax/obex/ObexHelper.java
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Copyright (C) 2015 Samsung LSI
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-
-/**
- * This class defines a set of helper methods for the implementation of Obex.
- * @hide
- */
-public final class ObexHelper {
-
-    private static final String TAG = "ObexHelper";
-    public static final boolean VDBG = false;
-    /**
-     * Defines the basic packet length used by OBEX. Every OBEX packet has the
-     * same basic format:<BR>
-     * Byte 0: Request or Response Code Byte 1&2: Length of the packet.
-     */
-    public static final int BASE_PACKET_LENGTH = 3;
-
-    /** Prevent object construction of helper class */
-    private ObexHelper() {
-    }
-
-    /**
-     * The maximum packet size for OBEX packets that this client can handle. At
-     * present, this must be changed for each port. TODO: The max packet size
-     * should be the Max incoming MTU minus TODO: L2CAP package headers and
-     * RFCOMM package headers. TODO: Retrieve the max incoming MTU from TODO:
-     * LocalDevice.getProperty().
-     * NOTE: This value must be larger than or equal to the L2CAP SDU
-     */
-    /*
-     * android note set as 0xFFFE to match remote MPS
-     */
-    public static final int MAX_PACKET_SIZE_INT = 0xFFFE;
-
-    // The minimum allowed max packet size is 255 according to the OBEX specification
-    public static final int LOWER_LIMIT_MAX_PACKET_SIZE = 255;
-
-    // The length of OBEX Byte Sequency Header Id according to the OBEX specification
-    public static final int OBEX_BYTE_SEQ_HEADER_LEN = 0x03;
-
-    /**
-     * Temporary workaround to be able to push files to Windows 7.
-     * TODO: Should be removed as soon as Microsoft updates their driver.
-     */
-    public static final int MAX_CLIENT_PACKET_SIZE = 0xFC00;
-
-    public static final int OBEX_OPCODE_FINAL_BIT_MASK = 0x80;
-
-    public static final int OBEX_OPCODE_CONNECT = 0x80;
-
-    public static final int OBEX_OPCODE_DISCONNECT = 0x81;
-
-    public static final int OBEX_OPCODE_PUT = 0x02;
-
-    public static final int OBEX_OPCODE_PUT_FINAL = 0x82;
-
-    public static final int OBEX_OPCODE_GET = 0x03;
-
-    public static final int OBEX_OPCODE_GET_FINAL = 0x83;
-
-    public static final int OBEX_OPCODE_RESERVED = 0x04;
-
-    public static final int OBEX_OPCODE_RESERVED_FINAL = 0x84;
-
-    public static final int OBEX_OPCODE_SETPATH = 0x85;
-
-    public static final int OBEX_OPCODE_ABORT = 0xFF;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ASCII = 0x00;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_1 = 0x01;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_2 = 0x02;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_3 = 0x03;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_4 = 0x04;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_5 = 0x05;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_6 = 0x06;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_7 = 0x07;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_8 = 0x08;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_9 = 0x09;
-
-    public static final int OBEX_AUTH_REALM_CHARSET_UNICODE = 0xFF;
-
-    public static final byte OBEX_SRM_ENABLE         = 0x01; // For BT we only need enable/disable
-    public static final byte OBEX_SRM_DISABLE        = 0x00;
-    public static final byte OBEX_SRM_SUPPORT        = 0x02; // Unused for now
-
-    public static final byte OBEX_SRMP_WAIT          = 0x01; // Only SRMP value used by BT
-
-    /**
-     * Updates the HeaderSet with the headers received in the byte array
-     * provided. Invalid headers are ignored.
-     * <P>
-     * The first two bits of an OBEX Header specifies the type of object that is
-     * being sent. The table below specifies the meaning of the high bits.
-     * <TABLE>
-     * <TR>
-     * <TH>Bits 8 and 7</TH>
-     * <TH>Value</TH>
-     * <TH>Description</TH>
-     * </TR>
-     * <TR>
-     * <TD>00</TD>
-     * <TD>0x00</TD>
-     * <TD>Null Terminated Unicode text, prefixed with 2 byte unsigned integer</TD>
-     * </TR>
-     * <TR>
-     * <TD>01</TD>
-     * <TD>0x40</TD>
-     * <TD>Byte Sequence, length prefixed with 2 byte unsigned integer</TD>
-     * </TR>
-     * <TR>
-     * <TD>10</TD>
-     * <TD>0x80</TD>
-     * <TD>1 byte quantity</TD>
-     * </TR>
-     * <TR>
-     * <TD>11</TD>
-     * <TD>0xC0</TD>
-     * <TD>4 byte quantity - transmitted in network byte order (high byte first</TD>
-     * </TR>
-     * </TABLE>
-     * This method uses the information in this table to determine the type of
-     * Java object to create and passes that object with the full header to
-     * setHeader() to update the HeaderSet object. Invalid headers will cause an
-     * exception to be thrown. When it is thrown, it is ignored.
-     * @param header the HeaderSet to update
-     * @param headerArray the byte array containing headers
-     * @return the result of the last start body or end body header provided;
-     *         the first byte in the result will specify if a body or end of
-     *         body is received
-     * @throws IOException if an invalid header was found
-     */
-    public static byte[] updateHeaderSet(HeaderSet header, byte[] headerArray) throws IOException {
-        int index = 0;
-        int length = 0;
-        int headerID;
-        byte[] value = null;
-        byte[] body = null;
-        HeaderSet headerImpl = header;
-        try {
-            while (index < headerArray.length) {
-                headerID = 0xFF & headerArray[index];
-                switch (headerID & (0xC0)) {
-
-                    /*
-                     * 0x00 is a unicode null terminate string with the first
-                     * two bytes after the header identifier being the length
-                     */
-                    case 0x00:
-                        // Fall through
-                        /*
-                         * 0x40 is a byte sequence with the first
-                         * two bytes after the header identifier being the length
-                         */
-                    case 0x40:
-                        boolean trimTail = true;
-                        index++;
-                        length = ((0xFF & headerArray[index]) << 8) +
-                                 (0xFF & headerArray[index + 1]);
-                        index += 2;
-                        if (length <= OBEX_BYTE_SEQ_HEADER_LEN) {
-                            Log.e(TAG, "Remote sent an OBEX packet with " +
-                                  "incorrect header length = " + length);
-                            break;
-                        }
-                        length -= OBEX_BYTE_SEQ_HEADER_LEN;
-                        value = new byte[length];
-                        System.arraycopy(headerArray, index, value, 0, length);
-                        if (length == 0 || (length > 0 && (value[length - 1] != 0))) {
-                            trimTail = false;
-                        }
-                        switch (headerID) {
-                            case HeaderSet.TYPE:
-                                try {
-                                    // Remove trailing null
-                                    if (trimTail == false) {
-                                        headerImpl.setHeader(headerID, new String(value, 0,
-                                                value.length, "ISO8859_1"));
-                                    } else {
-                                        headerImpl.setHeader(headerID, new String(value, 0,
-                                                value.length - 1, "ISO8859_1"));
-                                    }
-                                } catch (UnsupportedEncodingException e) {
-                                    throw e;
-                                }
-                                break;
-
-                            case HeaderSet.AUTH_CHALLENGE:
-                                headerImpl.mAuthChall = new byte[length];
-                                System.arraycopy(headerArray, index, headerImpl.mAuthChall, 0,
-                                        length);
-                                break;
-
-                            case HeaderSet.AUTH_RESPONSE:
-                                headerImpl.mAuthResp = new byte[length];
-                                System.arraycopy(headerArray, index, headerImpl.mAuthResp, 0,
-                                        length);
-                                break;
-
-                            case HeaderSet.BODY:
-                                /* Fall Through */
-                            case HeaderSet.END_OF_BODY:
-                                body = new byte[length + 1];
-                                body[0] = (byte)headerID;
-                                System.arraycopy(headerArray, index, body, 1, length);
-                                break;
-
-                            case HeaderSet.TIME_ISO_8601:
-                                try {
-                                    String dateString = new String(value, "ISO8859_1");
-                                    Calendar temp = Calendar.getInstance();
-                                    if ((dateString.length() == 16)
-                                            && (dateString.charAt(15) == 'Z')) {
-                                        temp.setTimeZone(TimeZone.getTimeZone("UTC"));
-                                    }
-                                    temp.set(Calendar.YEAR, Integer.parseInt(dateString.substring(
-                                            0, 4)));
-                                    temp.set(Calendar.MONTH, Integer.parseInt(dateString.substring(
-                                            4, 6)));
-                                    temp.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateString
-                                            .substring(6, 8)));
-                                    temp.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateString
-                                            .substring(9, 11)));
-                                    temp.set(Calendar.MINUTE, Integer.parseInt(dateString
-                                            .substring(11, 13)));
-                                    temp.set(Calendar.SECOND, Integer.parseInt(dateString
-                                            .substring(13, 15)));
-                                    headerImpl.setHeader(HeaderSet.TIME_ISO_8601, temp);
-                                } catch (UnsupportedEncodingException e) {
-                                    throw e;
-                                }
-                                break;
-
-                            default:
-                                if ((headerID & 0xC0) == 0x00) {
-                                    headerImpl.setHeader(headerID, ObexHelper.convertToUnicode(
-                                            value, true));
-                                } else {
-                                    headerImpl.setHeader(headerID, value);
-                                }
-                        }
-
-                        index += length;
-                        break;
-
-                    /*
-                     * 0x80 is a byte header.  The only valid byte headers are
-                     * the 16 user defined byte headers.
-                     */
-                    case 0x80:
-                        index++;
-                        try {
-                            headerImpl.setHeader(headerID, Byte.valueOf(headerArray[index]));
-                        } catch (Exception e) {
-                            // Not a valid header so ignore
-                        }
-                        index++;
-                        break;
-
-                    /*
-                     * 0xC0 is a 4 byte unsigned integer header and with the
-                     * exception of TIME_4_BYTE will be converted to a Long
-                     * and added.
-                     */
-                    case 0xC0:
-                        index++;
-                        value = new byte[4];
-                        System.arraycopy(headerArray, index, value, 0, 4);
-                        try {
-                            if (headerID != HeaderSet.TIME_4_BYTE) {
-                                // Determine if it is a connection ID.  These
-                                // need to be handled differently
-                                if (headerID == HeaderSet.CONNECTION_ID) {
-                                    headerImpl.mConnectionID = new byte[4];
-                                    System.arraycopy(value, 0, headerImpl.mConnectionID, 0, 4);
-                                } else {
-                                    headerImpl.setHeader(headerID, Long
-                                            .valueOf(convertToLong(value)));
-                                }
-                            } else {
-                                Calendar temp = Calendar.getInstance();
-                                temp.setTime(new Date(convertToLong(value) * 1000L));
-                                headerImpl.setHeader(HeaderSet.TIME_4_BYTE, temp);
-                            }
-                        } catch (Exception e) {
-                            // Not a valid header so ignore
-                            throw new IOException("Header was not formatted properly", e);
-                        }
-                        index += 4;
-                        break;
-                }
-
-            }
-        } catch (IOException e) {
-            throw new IOException("Header was not formatted properly", e);
-        }
-
-        return body;
-    }
-
-    /**
-     * Creates the header part of OBEX packet based on the header provided.
-     * TODO: Could use getHeaderList() to get the array of headers to include
-     * and then use the high two bits to determine the the type of the object
-     * and construct the byte array from that. This will make the size smaller.
-     * @param head the header used to construct the byte array
-     * @param nullOut <code>true</code> if the header should be set to
-     *        <code>null</code> once it is added to the array or
-     *        <code>false</code> if it should not be nulled out
-     * @return the header of an OBEX packet
-     */
-    public static byte[] createHeader(HeaderSet head, boolean nullOut) {
-        Long intHeader = null;
-        String stringHeader = null;
-        Calendar dateHeader = null;
-        Byte byteHeader = null;
-        StringBuffer buffer = null;
-        byte[] value = null;
-        byte[] result = null;
-        byte[] lengthArray = new byte[2];
-        int length;
-        HeaderSet headImpl = null;
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        headImpl = head;
-
-        try {
-            /*
-             * Determine if there is a connection ID to send.  If there is,
-             * then it should be the first header in the packet.
-             */
-            if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) {
-
-                out.write((byte)HeaderSet.CONNECTION_ID);
-                out.write(headImpl.mConnectionID);
-            }
-
-            // Count Header
-            intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT);
-            if (intHeader != null) {
-                out.write((byte)HeaderSet.COUNT);
-                value = ObexHelper.convertToByteArray(intHeader.longValue());
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.COUNT, null);
-                }
-            }
-
-            // Name Header
-            stringHeader = (String)headImpl.getHeader(HeaderSet.NAME);
-            if (stringHeader != null) {
-                out.write((byte)HeaderSet.NAME);
-                value = ObexHelper.convertToUnicodeByteArray(stringHeader);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(0xFF & (length >> 8));
-                lengthArray[1] = (byte)(0xFF & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.NAME, null);
-                }
-            } else if (headImpl.getEmptyNameHeader()) {
-                out.write((byte) HeaderSet.NAME);
-                lengthArray[0] = (byte) 0x00;
-                lengthArray[1] = (byte) 0x03;
-                out.write(lengthArray);
-            }
-
-            // Type Header
-            stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE);
-            if (stringHeader != null) {
-                out.write((byte)HeaderSet.TYPE);
-                try {
-                    value = stringHeader.getBytes("ISO8859_1");
-                } catch (UnsupportedEncodingException e) {
-                    throw e;
-                }
-
-                length = value.length + 4;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                out.write(0x00);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.TYPE, null);
-                }
-            }
-
-            // Length Header
-            intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH);
-            if (intHeader != null) {
-                out.write((byte)HeaderSet.LENGTH);
-                value = ObexHelper.convertToByteArray(intHeader.longValue());
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.LENGTH, null);
-                }
-            }
-
-            // Time ISO Header
-            dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601);
-            if (dateHeader != null) {
-
-                /*
-                 * The ISO Header should take the form YYYYMMDDTHHMMSSZ.  The
-                 * 'Z' will only be included if it is a UTC time.
-                 */
-                buffer = new StringBuffer();
-                int temp = dateHeader.get(Calendar.YEAR);
-                for (int i = temp; i < 1000; i = i * 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-                temp = dateHeader.get(Calendar.MONTH);
-                if (temp < 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-                temp = dateHeader.get(Calendar.DAY_OF_MONTH);
-                if (temp < 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-                buffer.append("T");
-                temp = dateHeader.get(Calendar.HOUR_OF_DAY);
-                if (temp < 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-                temp = dateHeader.get(Calendar.MINUTE);
-                if (temp < 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-                temp = dateHeader.get(Calendar.SECOND);
-                if (temp < 10) {
-                    buffer.append("0");
-                }
-                buffer.append(temp);
-
-                if (dateHeader.getTimeZone().getID().equals("UTC")) {
-                    buffer.append("Z");
-                }
-
-                try {
-                    value = buffer.toString().getBytes("ISO8859_1");
-                } catch (UnsupportedEncodingException e) {
-                    throw e;
-                }
-
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(HeaderSet.TIME_ISO_8601);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.TIME_ISO_8601, null);
-                }
-            }
-
-            // Time 4 Byte Header
-            dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE);
-            if (dateHeader != null) {
-                out.write(HeaderSet.TIME_4_BYTE);
-
-                /*
-                 * Need to call getTime() twice.  The first call will return
-                 * a java.util.Date object.  The second call returns the number
-                 * of milliseconds since January 1, 1970.  We need to convert
-                 * it to seconds since the TIME_4_BYTE expects the number of
-                 * seconds since January 1, 1970.
-                 */
-                value = ObexHelper.convertToByteArray(dateHeader.getTime().getTime() / 1000L);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.TIME_4_BYTE, null);
-                }
-            }
-
-            // Description Header
-            stringHeader = (String)headImpl.getHeader(HeaderSet.DESCRIPTION);
-            if (stringHeader != null) {
-                out.write((byte)HeaderSet.DESCRIPTION);
-                value = ObexHelper.convertToUnicodeByteArray(stringHeader);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.DESCRIPTION, null);
-                }
-            }
-
-            // Target Header
-            value = (byte[])headImpl.getHeader(HeaderSet.TARGET);
-            if (value != null) {
-                out.write((byte)HeaderSet.TARGET);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.TARGET, null);
-                }
-            }
-
-            // HTTP Header
-            value = (byte[])headImpl.getHeader(HeaderSet.HTTP);
-            if (value != null) {
-                out.write((byte)HeaderSet.HTTP);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.HTTP, null);
-                }
-            }
-
-            // Who Header
-            value = (byte[])headImpl.getHeader(HeaderSet.WHO);
-            if (value != null) {
-                out.write((byte)HeaderSet.WHO);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.WHO, null);
-                }
-            }
-
-            // Connection ID Header
-            value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER);
-            if (value != null) {
-                out.write((byte)HeaderSet.APPLICATION_PARAMETER);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.APPLICATION_PARAMETER, null);
-                }
-            }
-
-            // Object Class Header
-            value = (byte[])headImpl.getHeader(HeaderSet.OBJECT_CLASS);
-            if (value != null) {
-                out.write((byte)HeaderSet.OBJECT_CLASS);
-                length = value.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(value);
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.OBJECT_CLASS, null);
-                }
-            }
-
-            // Check User Defined Headers
-            for (int i = 0; i < 16; i++) {
-
-                //Unicode String Header
-                stringHeader = (String)headImpl.getHeader(i + 0x30);
-                if (stringHeader != null) {
-                    out.write((byte)i + 0x30);
-                    value = ObexHelper.convertToUnicodeByteArray(stringHeader);
-                    length = value.length + 3;
-                    lengthArray[0] = (byte)(255 & (length >> 8));
-                    lengthArray[1] = (byte)(255 & length);
-                    out.write(lengthArray);
-                    out.write(value);
-                    if (nullOut) {
-                        headImpl.setHeader(i + 0x30, null);
-                    }
-                }
-
-                // Byte Sequence Header
-                value = (byte[])headImpl.getHeader(i + 0x70);
-                if (value != null) {
-                    out.write((byte)i + 0x70);
-                    length = value.length + 3;
-                    lengthArray[0] = (byte)(255 & (length >> 8));
-                    lengthArray[1] = (byte)(255 & length);
-                    out.write(lengthArray);
-                    out.write(value);
-                    if (nullOut) {
-                        headImpl.setHeader(i + 0x70, null);
-                    }
-                }
-
-                // Byte Header
-                byteHeader = (Byte)headImpl.getHeader(i + 0xB0);
-                if (byteHeader != null) {
-                    out.write((byte)i + 0xB0);
-                    out.write(byteHeader.byteValue());
-                    if (nullOut) {
-                        headImpl.setHeader(i + 0xB0, null);
-                    }
-                }
-
-                // Integer header
-                intHeader = (Long)headImpl.getHeader(i + 0xF0);
-                if (intHeader != null) {
-                    out.write((byte)i + 0xF0);
-                    out.write(ObexHelper.convertToByteArray(intHeader.longValue()));
-                    if (nullOut) {
-                        headImpl.setHeader(i + 0xF0, null);
-                    }
-                }
-            }
-
-            // Add the authentication challenge header
-            if (headImpl.mAuthChall != null) {
-                out.write((byte)HeaderSet.AUTH_CHALLENGE);
-                length = headImpl.mAuthChall.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(headImpl.mAuthChall);
-                if (nullOut) {
-                    headImpl.mAuthChall = null;
-                }
-            }
-
-            // Add the authentication response header
-            if (headImpl.mAuthResp != null) {
-                out.write((byte)HeaderSet.AUTH_RESPONSE);
-                length = headImpl.mAuthResp.length + 3;
-                lengthArray[0] = (byte)(255 & (length >> 8));
-                lengthArray[1] = (byte)(255 & length);
-                out.write(lengthArray);
-                out.write(headImpl.mAuthResp);
-                if (nullOut) {
-                    headImpl.mAuthResp = null;
-                }
-            }
-
-            // TODO:
-            // If the SRM and SRMP header is in use, they must be send in the same OBEX packet
-            // But the current structure of the obex code cannot handle this, and therefore
-            // it makes sense to put them in the tail of the headers, since we then reduce the
-            // chance of enabling SRM to soon. The down side is that SRM cannot be used while
-            // transferring non-body headers
-
-            // Add the SRM header
-            byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
-            if (byteHeader != null) {
-                out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE);
-                out.write(byteHeader.byteValue());
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null);
-                }
-            }
-
-            // Add the SRM parameter header
-            byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
-            if (byteHeader != null) {
-                out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
-                out.write(byteHeader.byteValue());
-                if (nullOut) {
-                    headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
-                }
-            }
-
-        } catch (IOException e) {
-        } finally {
-            result = out.toByteArray();
-            try {
-                out.close();
-            } catch (Exception ex) {
-            }
-        }
-
-        return result;
-
-    }
-
-    /**
-     * Determines where the maximum divide is between headers. This method is
-     * used by put and get operations to separate headers to a size that meets
-     * the max packet size allowed.
-     * @param headerArray the headers to separate
-     * @param start the starting index to search
-     * @param maxSize the maximum size of a packet
-     * @return the index of the end of the header block to send or -1 if the
-     *         header could not be divided because the header is too large
-     */
-    public static int findHeaderEnd(byte[] headerArray, int start, int maxSize) {
-
-        int fullLength = 0;
-        int lastLength = -1;
-        int index = start;
-        int length = 0;
-
-        // TODO: Ensure SRM and SRMP headers are not split into two OBEX packets
-
-        while ((fullLength < maxSize) && (index < headerArray.length)) {
-            int headerID = (headerArray[index] < 0 ? headerArray[index] + 256 : headerArray[index]);
-            lastLength = fullLength;
-
-            switch (headerID & (0xC0)) {
-
-                case 0x00:
-                    // Fall through
-                case 0x40:
-
-                    index++;
-                    length = (headerArray[index] < 0 ? headerArray[index] + 256
-                            : headerArray[index]);
-                    length = length << 8;
-                    index++;
-                    length += (headerArray[index] < 0 ? headerArray[index] + 256
-                            : headerArray[index]);
-                    length -= 3;
-                    index++;
-                    index += length;
-                    fullLength += length + 3;
-                    break;
-
-                case 0x80:
-
-                    index++;
-                    index++;
-                    fullLength += 2;
-                    break;
-
-                case 0xC0:
-
-                    index += 5;
-                    fullLength += 5;
-                    break;
-
-            }
-
-        }
-
-        /*
-         * Determine if this is the last header or not
-         */
-        if (lastLength == 0) {
-            /*
-             * Since this is the last header, check to see if the size of this
-             * header is less then maxSize.  If it is, return the length of the
-             * header, otherwise return -1.  The length of the header is
-             * returned since it would be the start of the next header
-             */
-            if (fullLength < maxSize) {
-                return headerArray.length;
-            } else {
-                return -1;
-            }
-        } else {
-            return lastLength + start;
-        }
-    }
-
-    /**
-     * Converts the byte array to a long.
-     * @param b the byte array to convert to a long
-     * @return the byte array as a long
-     */
-    public static long convertToLong(byte[] b) {
-        long result = 0;
-        long value = 0;
-        long power = 0;
-
-        for (int i = (b.length - 1); i >= 0; i--) {
-            value = b[i];
-            if (value < 0) {
-                value += 256;
-            }
-
-            result = result | (value << power);
-            power += 8;
-        }
-
-        return result;
-    }
-
-    /**
-     * Converts the long to a 4 byte array. The long must be non negative.
-     * @param l the long to convert
-     * @return a byte array that is the same as the long
-     */
-    public static byte[] convertToByteArray(long l) {
-        byte[] b = new byte[4];
-
-        b[0] = (byte)(255 & (l >> 24));
-        b[1] = (byte)(255 & (l >> 16));
-        b[2] = (byte)(255 & (l >> 8));
-        b[3] = (byte)(255 & l);
-
-        return b;
-    }
-
-    /**
-     * Converts the String to a UNICODE byte array. It will also add the ending
-     * null characters to the end of the string.
-     * @param s the string to convert
-     * @return the unicode byte array of the string
-     */
-    public static byte[] convertToUnicodeByteArray(String s) {
-        if (s == null) {
-            return null;
-        }
-
-        char c[] = s.toCharArray();
-        byte[] result = new byte[(c.length * 2) + 2];
-        for (int i = 0; i < c.length; i++) {
-            result[(i * 2)] = (byte)(c[i] >> 8);
-            result[((i * 2) + 1)] = (byte)c[i];
-        }
-
-        // Add the UNICODE null character
-        result[result.length - 2] = 0;
-        result[result.length - 1] = 0;
-
-        return result;
-    }
-
-    /**
-     * Retrieves the value from the byte array for the tag value specified. The
-     * array should be of the form Tag - Length - Value triplet.
-     * @param tag the tag to retrieve from the byte array
-     * @param triplet the byte sequence containing the tag length value form
-     * @return the value of the specified tag
-     */
-    public static byte[] getTagValue(byte tag, byte[] triplet) {
-
-        int index = findTag(tag, triplet);
-        if (index == -1) {
-            return null;
-        }
-
-        index++;
-        int length = triplet[index] & 0xFF;
-
-        byte[] result = new byte[length];
-        index++;
-        System.arraycopy(triplet, index, result, 0, length);
-
-        return result;
-    }
-
-    /**
-     * Finds the index that starts the tag value pair in the byte array provide.
-     * @param tag the tag to look for
-     * @param value the byte array to search
-     * @return the starting index of the tag or -1 if the tag could not be found
-     */
-    public static int findTag(byte tag, byte[] value) {
-        int length = 0;
-
-        if (value == null) {
-            return -1;
-        }
-
-        int index = 0;
-
-        while ((index < value.length) && (value[index] != tag)) {
-            length = value[index + 1] & 0xFF;
-            index += length + 2;
-        }
-
-        if (index >= value.length) {
-            return -1;
-        }
-
-        return index;
-    }
-
-    /**
-     * Converts the byte array provided to a unicode string.
-     * @param b the byte array to convert to a string
-     * @param includesNull determine if the byte string provided contains the
-     *        UNICODE null character at the end or not; if it does, it will be
-     *        removed
-     * @return a Unicode string
-     * @throws IllegalArgumentException if the byte array has an odd length
-     */
-    public static String convertToUnicode(byte[] b, boolean includesNull) {
-        if (b == null || b.length == 0) {
-            return null;
-        }
-        int arrayLength = b.length;
-        if (!((arrayLength % 2) == 0)) {
-            throw new IllegalArgumentException("Byte array not of a valid form");
-        }
-        arrayLength = (arrayLength >> 1);
-        if (includesNull) {
-            arrayLength -= 1;
-        }
-
-        char[] c = new char[arrayLength];
-        for (int i = 0; i < arrayLength; i++) {
-            int upper = b[2 * i];
-            int lower = b[(2 * i) + 1];
-            if (upper < 0) {
-                upper += 256;
-            }
-            if (lower < 0) {
-                lower += 256;
-            }
-            // If upper and lower both equal 0, it should be the end of string.
-            // Ignore left bytes from array to avoid potential issues
-            if (upper == 0 && lower == 0) {
-                return new String(c, 0, i);
-            }
-
-            c[i] = (char)((upper << 8) | lower);
-        }
-
-        return new String(c);
-    }
-
-    /**
-     * Compute the MD5 hash of the byte array provided. Does not accumulate
-     * input.
-     * @param in the byte array to hash
-     * @return the MD5 hash of the byte array
-     */
-    public static byte[] computeMd5Hash(byte[] in) {
-        try {
-            MessageDigest md5 = MessageDigest.getInstance("MD5");
-            return md5.digest(in);
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Computes an authentication challenge header.
-     * @param nonce the challenge that will be provided to the peer; the
-     *        challenge must be 16 bytes long
-     * @param realm a short description that describes what password to use
-     * @param access if <code>true</code> then full access will be granted if
-     *        successful; if <code>false</code> then read only access will be
-     *        granted if successful
-     * @param userID if <code>true</code>, a user ID is required in the reply;
-     *        if <code>false</code>, no user ID is required
-     * @throws IllegalArgumentException if the challenge is not 16 bytes long;
-     *         if the realm can not be encoded in less then 255 bytes
-     * @throws IOException if the encoding scheme ISO 8859-1 is not supported
-     */
-    public static byte[] computeAuthenticationChallenge(byte[] nonce, String realm, boolean access,
-            boolean userID) throws IOException {
-        byte[] authChall = null;
-
-        if (nonce.length != 16) {
-            throw new IllegalArgumentException("Nonce must be 16 bytes long");
-        }
-
-        /*
-         * The authentication challenge is a byte sequence of the following form
-         * byte 0: 0x00 - the tag for the challenge
-         * byte 1: 0x10 - the length of the challenge; must be 16
-         * byte 2-17: the authentication challenge
-         * byte 18: 0x01 - the options tag; this is optional in the spec, but
-         *                 we are going to include it in every message
-         * byte 19: 0x01 - length of the options; must be 1
-         * byte 20: the value of the options; bit 0 is set if user ID is
-         *          required; bit 1 is set if access mode is read only
-         * byte 21: 0x02 - the tag for authentication realm; only included if
-         *                 an authentication realm is specified
-         * byte 22: the length of the authentication realm; only included if
-         *          the authentication realm is specified
-         * byte 23: the encoding scheme of the authentication realm; we will use
-         *          the ISO 8859-1 encoding scheme since it is part of the KVM
-         * byte 24 & up: the realm if one is specified.
-         */
-        if (realm == null) {
-            authChall = new byte[21];
-        } else {
-            if (realm.length() >= 255) {
-                throw new IllegalArgumentException("Realm must be less then 255 bytes");
-            }
-            authChall = new byte[24 + realm.length()];
-            authChall[21] = 0x02;
-            authChall[22] = (byte)(realm.length() + 1);
-            authChall[23] = 0x01; // ISO 8859-1 Encoding
-            System.arraycopy(realm.getBytes("ISO8859_1"), 0, authChall, 24, realm.length());
-        }
-
-        // Include the nonce field in the header
-        authChall[0] = 0x00;
-        authChall[1] = 0x10;
-        System.arraycopy(nonce, 0, authChall, 2, 16);
-
-        // Include the options header
-        authChall[18] = 0x01;
-        authChall[19] = 0x01;
-        authChall[20] = 0x00;
-
-        if (!access) {
-            authChall[20] = (byte)(authChall[20] | 0x02);
-        }
-        if (userID) {
-            authChall[20] = (byte)(authChall[20] | 0x01);
-        }
-
-        return authChall;
-    }
-
-    /**
-     * Return the maximum allowed OBEX packet to transmit.
-     * OBEX packets transmitted must be smaller than this value.
-     * @param transport Reference to the ObexTransport in use.
-     * @return the maximum allowed OBEX packet to transmit
-     */
-    public static int getMaxTxPacketSize(ObexTransport transport) {
-        int size = transport.getMaxTransmitPacketSize();
-        return validateMaxPacketSize(size);
-    }
-
-    /**
-     * Return the maximum allowed OBEX packet to receive - used in OBEX connect.
-     * @param transport
-     * @return he maximum allowed OBEX packet to receive
-     */
-    public static int getMaxRxPacketSize(ObexTransport transport) {
-        int size = transport.getMaxReceivePacketSize();
-        return validateMaxPacketSize(size);
-    }
-
-    private static int validateMaxPacketSize(int size) {
-        if (VDBG && (size > MAX_PACKET_SIZE_INT)) {
-            Log.w(TAG, "The packet size supported for the connection (" + size + ") is larger"
-                    + " than the configured OBEX packet size: " + MAX_PACKET_SIZE_INT);
-        }
-        if (size != -1 && size < MAX_PACKET_SIZE_INT) {
-            if (size < LOWER_LIMIT_MAX_PACKET_SIZE) {
-                throw new IllegalArgumentException(size + " is less that the lower limit: "
-                        + LOWER_LIMIT_MAX_PACKET_SIZE);
-            }
-            return size;
-        }
-        return MAX_PACKET_SIZE_INT;
-    }
-}
diff --git a/obex/javax/obex/ObexSession.java b/obex/javax/obex/ObexSession.java
deleted file mode 100644
index 542b9c8..0000000
--- a/obex/javax/obex/ObexSession.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-
-import android.util.Log;
-
-/**
- * The <code>ObexSession</code> interface characterizes the term
- * "OBEX Connection" as defined in the IrDA Object Exchange Protocol v1.2, which
- * could be the server-side view of an OBEX connection, or the client-side view
- * of the same connection, which is established by server's accepting of a
- * client issued "CONNECT".
- * <P>
- * This interface serves as the common super class for
- * <CODE>ClientSession</CODE> and <CODE>ServerSession</CODE>.
- * @hide
- */
-public class ObexSession {
-
-    private static final String TAG = "ObexSession";
-    private static final boolean V = ObexHelper.VDBG;
-
-    protected Authenticator mAuthenticator;
-
-    protected byte[] mChallengeDigest;
-
-    /**
-     * Called when the server received an authentication challenge header. This
-     * will cause the authenticator to handle the authentication challenge.
-     * @param header the header with the authentication challenge
-     * @return <code>true</code> if the last request should be resent;
-     *         <code>false</code> if the last request should not be resent
-     * @throws IOException
-     */
-    public boolean handleAuthChall(HeaderSet header) throws IOException {
-        if (mAuthenticator == null) {
-            return false;
-        }
-
-        /*
-         * An authentication challenge is made up of one required and two
-         * optional tag length value triplets. The tag 0x00 is required to be in
-         * the authentication challenge and it represents the challenge digest
-         * that was received. The tag 0x01 is the options tag. This tag tracks
-         * if user ID is required and if full access will be granted. The tag
-         * 0x02 is the realm, which provides a description of which user name
-         * and password to use.
-         */
-        byte[] challenge = ObexHelper.getTagValue((byte)0x00, header.mAuthChall);
-        byte[] option = ObexHelper.getTagValue((byte)0x01, header.mAuthChall);
-        byte[] description = ObexHelper.getTagValue((byte)0x02, header.mAuthChall);
-
-        String realm = null;
-        if (description != null) {
-            byte[] realmString = new byte[description.length - 1];
-            System.arraycopy(description, 1, realmString, 0, realmString.length);
-
-            switch (description[0] & 0xFF) {
-
-                case ObexHelper.OBEX_AUTH_REALM_CHARSET_ASCII:
-                    // ASCII encoding
-                    // Fall through
-                case ObexHelper.OBEX_AUTH_REALM_CHARSET_ISO_8859_1:
-                    // ISO-8859-1 encoding
-                    try {
-                        realm = new String(realmString, "ISO8859_1");
-                    } catch (Exception e) {
-                        throw new IOException("Unsupported Encoding Scheme");
-                    }
-                    break;
-
-                case ObexHelper.OBEX_AUTH_REALM_CHARSET_UNICODE:
-                    // UNICODE Encoding
-                    realm = ObexHelper.convertToUnicode(realmString, false);
-                    break;
-
-                default:
-                    throw new IOException("Unsupported Encoding Scheme");
-            }
-        }
-
-        boolean isUserIDRequired = false;
-        boolean isFullAccess = true;
-        if (option != null) {
-            if ((option[0] & 0x01) != 0) {
-                isUserIDRequired = true;
-            }
-
-            if ((option[0] & 0x02) != 0) {
-                isFullAccess = false;
-            }
-        }
-
-        PasswordAuthentication result = null;
-        header.mAuthChall = null;
-
-        try {
-            result = mAuthenticator
-                    .onAuthenticationChallenge(realm, isUserIDRequired, isFullAccess);
-        } catch (Exception e) {
-            if (V) Log.d(TAG, "Exception occured - returning false", e);
-            return false;
-        }
-
-        /*
-         * If no password is provided then we not resent the request
-         */
-        if (result == null) {
-            return false;
-        }
-
-        byte[] password = result.getPassword();
-        if (password == null) {
-            return false;
-        }
-
-        byte[] userName = result.getUserName();
-
-        /*
-         * Create the authentication response header. It includes 1 required and
-         * 2 option tag length value triples. The required triple has a tag of
-         * 0x00 and is the response digest. The first optional tag is 0x01 and
-         * represents the user ID. If no user ID is provided, then no user ID
-         * will be sent. The second optional tag is 0x02 and is the challenge
-         * that was received. This will always be sent
-         */
-        if (userName != null) {
-            header.mAuthResp = new byte[38 + userName.length];
-            header.mAuthResp[36] = (byte)0x01;
-            header.mAuthResp[37] = (byte)userName.length;
-            System.arraycopy(userName, 0, header.mAuthResp, 38, userName.length);
-        } else {
-            header.mAuthResp = new byte[36];
-        }
-
-        // Create the secret String
-        byte[] digest = new byte[challenge.length + password.length + 1];
-        System.arraycopy(challenge, 0, digest, 0, challenge.length);
-        // Insert colon between challenge and password
-        digest[challenge.length] = (byte)0x3A;
-        System.arraycopy(password, 0, digest, challenge.length + 1, password.length);
-
-        // Add the Response Digest
-        header.mAuthResp[0] = (byte)0x00;
-        header.mAuthResp[1] = (byte)0x10;
-
-        System.arraycopy(ObexHelper.computeMd5Hash(digest), 0, header.mAuthResp, 2, 16);
-
-        // Add the challenge
-        header.mAuthResp[18] = (byte)0x02;
-        header.mAuthResp[19] = (byte)0x10;
-        System.arraycopy(challenge, 0, header.mAuthResp, 20, 16);
-
-        return true;
-    }
-
-    /**
-     * Called when the server received an authentication response header. This
-     * will cause the authenticator to handle the authentication response.
-     * @param authResp the authentication response
-     * @return <code>true</code> if the response passed; <code>false</code> if
-     *         the response failed
-     */
-    public boolean handleAuthResp(byte[] authResp) {
-        if (mAuthenticator == null) {
-            return false;
-        }
-        // get the correct password from the application
-        byte[] correctPassword = mAuthenticator.onAuthenticationResponse(ObexHelper.getTagValue(
-                (byte)0x01, authResp));
-        if (correctPassword == null) {
-            return false;
-        }
-
-        byte[] temp = new byte[correctPassword.length + 16];
-
-        System.arraycopy(mChallengeDigest, 0, temp, 0, 16);
-        System.arraycopy(correctPassword, 0, temp, 16, correctPassword.length);
-
-        byte[] correctResponse = ObexHelper.computeMd5Hash(temp);
-        byte[] actualResponse = ObexHelper.getTagValue((byte)0x00, authResp);
-
-        // compare the MD5 hash array .
-        for (int i = 0; i < 16; i++) {
-            if (correctResponse[i] != actualResponse[i]) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/obex/javax/obex/ObexTransport.java b/obex/javax/obex/ObexTransport.java
deleted file mode 100644
index 4cef0b3..0000000
--- a/obex/javax/obex/ObexTransport.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * The <code>ObexTransport</code> interface defines the underlying transport
- * connection which carries the OBEX protocol( such as TCP, RFCOMM device file
- * exposed by Bluetooth or USB in kernel, RFCOMM socket emulated in Android
- * platform, Irda). This interface provides an abstract layer to be used by the
- * <code>ObexConnection</code>. Each kind of medium shall have its own
- * implementation to wrap and follow the same interface.
- * <P>
- * See section 1.2.2 of IrDA Object Exchange Protocol specification.
- * <P>
- * Different kind of medium may have different construction - for example, the
- * RFCOMM device file medium may be constructed from a file descriptor or simply
- * a string while the TCP medium usually from a socket.
- * @hide
- */
-public interface ObexTransport {
-
-    void create() throws IOException;
-
-    void listen() throws IOException;
-
-    void close() throws IOException;
-
-    void connect() throws IOException;
-
-    void disconnect() throws IOException;
-
-    InputStream openInputStream() throws IOException;
-
-    OutputStream openOutputStream() throws IOException;
-
-    DataInputStream openDataInputStream() throws IOException;
-
-    DataOutputStream openDataOutputStream() throws IOException;
-
-    /**
-     * Must return the maximum allowed OBEX packet that can be sent over
-     * the transport. For L2CAP this will be the Max SDU reported by the
-     * peer device.
-     * The returned value will be used to set the outgoing OBEX packet
-     * size. Therefore this value shall not change.
-     * For RFCOMM or other transport types where the OBEX packets size
-     * is unrelated to the transport packet size, return -1;
-     * Exception can be made (like PBAP transport) with a smaller value
-     * to avoid bad effect on other profiles using the RFCOMM;
-     * @return the maximum allowed OBEX packet that can be send over
-     *         the transport. Or -1 in case of don't care.
-     */
-    int getMaxTransmitPacketSize();
-
-    /**
-     * Must return the maximum allowed OBEX packet that can be received over
-     * the transport. For L2CAP this will be the Max SDU configured for the
-     * L2CAP channel.
-     * The returned value will be used to validate the incoming packet size
-     * values.
-     * For RFCOMM or other transport types where the OBEX packets size
-     * is unrelated to the transport packet size, return -1;
-     * @return the maximum allowed OBEX packet that can be send over
-     *         the transport. Or -1 in case of don't care.
-     */
-    int getMaxReceivePacketSize();
-
-    /**
-     * Shall return true if the transport in use supports SRM.
-     * @return
-     *        <code>true</code> if SRM operation is supported, and is to be enabled.
-     *        <code>false</code> if SRM operations are not supported, or should not be used.
-     */
-    boolean isSrmSupported();
-
-
-}
diff --git a/obex/javax/obex/Operation.java b/obex/javax/obex/Operation.java
deleted file mode 100644
index 5b4d5ac..0000000
--- a/obex/javax/obex/Operation.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * The <code>Operation</code> interface provides ways to manipulate a single
- * OBEX PUT or GET operation. The implementation of this interface sends OBEX
- * packets as they are built. If during the operation the peer in the operation
- * ends the operation, an <code>IOException</code> is thrown on the next read
- * from the input stream, write to the output stream, or call to
- * <code>sendHeaders()</code>.
- * <P>
- * <STRONG>Definition of methods inherited from <code>ContentConnection</code>
- * </STRONG>
- * <P>
- * <code>getEncoding()</code> will always return <code>null</code>. <BR>
- * <code>getLength()</code> will return the length specified by the OBEX Length
- * header or -1 if the OBEX Length header was not included. <BR>
- * <code>getType()</code> will return the value specified in the OBEX Type
- * header or <code>null</code> if the OBEX Type header was not included.<BR>
- * <P>
- * <STRONG>How Headers are Handled</STRONG>
- * <P>
- * As headers are received, they may be retrieved through the
- * <code>getReceivedHeaders()</code> method. If new headers are set during the
- * operation, the new headers will be sent during the next packet exchange.
- * <P>
- * <STRONG>PUT example</STRONG>
- * <P>
- * <PRE>
- * void putObjectViaOBEX(ClientSession conn, HeaderSet head, byte[] obj) throws IOException {
- *     // Include the length header
- *     head.setHeader(head.LENGTH, new Long(obj.length));
- *     // Initiate the PUT request
- *     Operation op = conn.put(head);
- *     // Open the output stream to put the object to it
- *     DataOutputStream out = op.openDataOutputStream();
- *     // Send the object to the server
- *     out.write(obj);
- *     // End the transaction
- *     out.close();
- *     op.close();
- * }
- * </PRE>
- * <P>
- * <STRONG>GET example</STRONG>
- * <P>
- * <PRE>
- * byte[] getObjectViaOBEX(ClientSession conn, HeaderSet head) throws IOException {
- *     // Send the initial GET request to the server
- *     Operation op = conn.get(head);
- *     // Retrieve the length of the object being sent back
- *     int length = op.getLength();
- *     // Create space for the object
- *     byte[] obj = new byte[length];
- *     // Get the object from the input stream
- *     DataInputStream in = trans.openDataInputStream();
- *     in.read(obj);
- *     // End the transaction
- *     in.close();
- *     op.close();
- *     return obj;
- * }
- * </PRE>
- *
- * <H3>Client PUT Operation Flow</H3> For PUT operations, a call to
- * <code>close()</code> the <code>OutputStream</code> returned from
- * <code>openOutputStream()</code> or <code>openDataOutputStream()</code> will
- * signal that the request is done. (In OBEX terms, the End-Of-Body header
- * should be sent and the final bit in the request will be set.) At this point,
- * the reply from the server may begin to be processed. A call to
- * <code>getResponseCode()</code> will do an implicit close on the
- * <code>OutputStream</code> and therefore signal that the request is done.
- * <H3>Client GET Operation Flow</H3> For GET operation, a call to
- * <code>openInputStream()</code> or <code>openDataInputStream()</code> will
- * signal that the request is done. (In OBEX terms, the final bit in the request
- * will be set.) A call to <code>getResponseCode()</code> will cause an implicit
- * close on the <code>InputStream</code>. No further data may be read at this
- * point.
- * @hide
- */
-public interface Operation {
-
-    /**
-     * Sends an ABORT message to the server. By calling this method, the
-     * corresponding input and output streams will be closed along with this
-     * object. No headers are sent in the abort request. This will end the
-     * operation since <code>close()</code> will be called by this method.
-     * @throws IOException if the transaction has already ended or if an OBEX
-     *         server calls this method
-     */
-    void abort() throws IOException;
-
-    /**
-     * Returns the headers that have been received during the operation.
-     * Modifying the object returned has no effect on the headers that are sent
-     * or retrieved.
-     * @return the headers received during this <code>Operation</code>
-     * @throws IOException if this <code>Operation</code> has been closed
-     */
-    HeaderSet getReceivedHeader() throws IOException;
-
-    /**
-     * Specifies the headers that should be sent in the next OBEX message that
-     * is sent.
-     * @param headers the headers to send in the next message
-     * @throws IOException if this <code>Operation</code> has been closed or the
-     *         transaction has ended and no further messages will be exchanged
-     * @throws IllegalArgumentException if <code>headers</code> was not created
-     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
-     *         or <code>ClientSession.createHeaderSet()</code>
-     * @throws NullPointerException if <code>headers</code> if <code>null</code>
-     */
-    void sendHeaders(HeaderSet headers) throws IOException;
-
-    /**
-     * Returns the response code received from the server. Response codes are
-     * defined in the <code>ResponseCodes</code> class.
-     * @see ResponseCodes
-     * @return the response code retrieved from the server
-     * @throws IOException if an error occurred in the transport layer during
-     *         the transaction; if this object was created by an OBEX server
-     */
-    int getResponseCode() throws IOException;
-
-    String getEncoding();
-
-    long getLength();
-
-    int getHeaderLength();
-
-    String getType();
-
-    InputStream openInputStream() throws IOException;
-
-    DataInputStream openDataInputStream() throws IOException;
-
-    OutputStream openOutputStream() throws IOException;
-
-    DataOutputStream openDataOutputStream() throws IOException;
-
-    void close() throws IOException;
-
-    int getMaxPacketSize();
-
-    public void noBodyHeader();
-}
diff --git a/obex/javax/obex/PasswordAuthentication.java b/obex/javax/obex/PasswordAuthentication.java
deleted file mode 100644
index 326b1ff..0000000
--- a/obex/javax/obex/PasswordAuthentication.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-/**
- * This class holds user name and password combinations.
- * @hide
- */
-public final class PasswordAuthentication {
-
-    private byte[] mUserName;
-
-    private final byte[] mPassword;
-
-    /**
-     * Creates a new <code>PasswordAuthentication</code> with the user name and
-     * password provided.
-     * @param userName the user name to include; this may be <code>null</code>
-     * @param password the password to include in the response
-     * @throws NullPointerException if <code>password</code> is
-     *         <code>null</code>
-     */
-    public PasswordAuthentication(final byte[] userName, final byte[] password) {
-        if (userName != null) {
-            mUserName = new byte[userName.length];
-            System.arraycopy(userName, 0, mUserName, 0, userName.length);
-        }
-
-        mPassword = new byte[password.length];
-        System.arraycopy(password, 0, mPassword, 0, password.length);
-    }
-
-    /**
-     * Retrieves the user name that was specified in the constructor. The user
-     * name may be <code>null</code>.
-     * @return the user name
-     */
-    public byte[] getUserName() {
-        return mUserName;
-    }
-
-    /**
-     * Retrieves the password.
-     * @return the password
-     */
-    public byte[] getPassword() {
-        return mPassword;
-    }
-}
diff --git a/obex/javax/obex/PrivateInputStream.java b/obex/javax/obex/PrivateInputStream.java
deleted file mode 100644
index 5daee72..0000000
--- a/obex/javax/obex/PrivateInputStream.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * This object provides an input stream to the Operation objects used in this
- * package.
- * @hide
- */
-public final class PrivateInputStream extends InputStream {
-
-    private BaseStream mParent;
-
-    private byte[] mData;
-
-    private int mIndex;
-
-    private boolean mOpen;
-
-    /**
-     * Creates an input stream for the <code>Operation</code> to read from
-     * @param p the connection this input stream is for
-     */
-    public PrivateInputStream(BaseStream p) {
-        mParent = p;
-        mData = new byte[0];
-        mIndex = 0;
-        mOpen = true;
-    }
-
-    /**
-     * Returns the number of bytes that can be read (or skipped over) from this
-     * input stream without blocking by the next caller of a method for this
-     * input stream. The next caller might be the same thread or or another
-     * thread.
-     * @return the number of bytes that can be read from this input stream
-     *         without blocking
-     * @throws IOException if an I/O error occurs
-     */
-    @Override
-    public synchronized int available() throws IOException {
-        ensureOpen();
-        return mData.length - mIndex;
-    }
-
-    /**
-     * Reads the next byte of data from the input stream. The value byte is
-     * returned as an int in the range 0 to 255. If no byte is available because
-     * the end of the stream has been reached, the value -1 is returned. This
-     * method blocks until input data is available, the end of the stream is
-     * detected, or an exception is thrown.
-     * @return the byte read from the input stream or -1 if it reaches the end of
-     *         stream
-     * @throws IOException if an I/O error occurs
-     */
-    @Override
-    public synchronized int read() throws IOException {
-        ensureOpen();
-        while (mData.length == mIndex) {
-            if (!mParent.continueOperation(true, true)) {
-                return -1;
-            }
-        }
-        return (mData[mIndex++] & 0xFF);
-    }
-
-    @Override
-    public int read(byte[] b) throws IOException {
-        return read(b, 0, b.length);
-    }
-
-    @Override
-    public synchronized int read(byte[] b, int offset, int length) throws IOException {
-
-        if (b == null) {
-            throw new IOException("buffer is null");
-        }
-        if ((offset | length) < 0 || length > b.length - offset) {
-            throw new ArrayIndexOutOfBoundsException("index outof bound");
-        }
-        ensureOpen();
-
-        int currentDataLength = mData.length - mIndex;
-        int remainReadLength = length;
-        int offset1 = offset;
-        int result = 0;
-
-        while (currentDataLength <= remainReadLength) {
-            System.arraycopy(mData, mIndex, b, offset1, currentDataLength);
-            mIndex += currentDataLength;
-            offset1 += currentDataLength;
-            result += currentDataLength;
-            remainReadLength -= currentDataLength;
-
-            if (!mParent.continueOperation(true, true)) {
-                return result == 0 ? -1 : result;
-            }
-            currentDataLength = mData.length - mIndex;
-        }
-        if (remainReadLength > 0) {
-            System.arraycopy(mData, mIndex, b, offset1, remainReadLength);
-            mIndex += remainReadLength;
-            result += remainReadLength;
-        }
-        return result;
-    }
-
-    /**
-     * Allows the <code>OperationImpl</code> thread to add body data to the
-     * input stream.
-     * @param body the data to add to the stream
-     * @param start the start of the body to array to copy
-     */
-    public synchronized void writeBytes(byte[] body, int start) {
-
-        int length = (body.length - start) + (mData.length - mIndex);
-        byte[] temp = new byte[length];
-
-        System.arraycopy(mData, mIndex, temp, 0, mData.length - mIndex);
-        System.arraycopy(body, start, temp, mData.length - mIndex, body.length - start);
-
-        mData = temp;
-        mIndex = 0;
-        notifyAll();
-    }
-
-    /**
-     * Verifies that this stream is open
-     * @throws IOException if the stream is not open
-     */
-    private void ensureOpen() throws IOException {
-        mParent.ensureOpen();
-        if (!mOpen) {
-            throw new IOException("Input stream is closed");
-        }
-    }
-
-    /**
-     * Closes the input stream. If the input stream is already closed, do
-     * nothing.
-     * @throws IOException this will never happen
-     */
-    @Override
-    public void close() throws IOException {
-        mOpen = false;
-        mParent.streamClosed(true);
-    }
-}
diff --git a/obex/javax/obex/PrivateOutputStream.java b/obex/javax/obex/PrivateOutputStream.java
deleted file mode 100644
index 713f4ae..0000000
--- a/obex/javax/obex/PrivateOutputStream.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-
-/**
- * This object provides an output stream to the Operation objects used in this
- * package.
- * @hide
- */
-public final class PrivateOutputStream extends OutputStream {
-
-    private BaseStream mParent;
-
-    private ByteArrayOutputStream mArray;
-
-    private boolean mOpen;
-
-    private int mMaxPacketSize;
-
-    /**
-     * Creates an empty <code>PrivateOutputStream</code> to write to.
-     * @param p the connection that this stream runs over
-     */
-    public PrivateOutputStream(BaseStream p, int maxSize) {
-        mParent = p;
-        mArray = new ByteArrayOutputStream();
-        mMaxPacketSize = maxSize;
-        mOpen = true;
-    }
-
-    /**
-     * Determines how many bytes have been written to the output stream.
-     * @return the number of bytes written to the output stream
-     */
-    public int size() {
-        return mArray.size();
-    }
-
-    /**
-     * Writes the specified byte to this output stream. The general contract for
-     * write is that one byte is written to the output stream. The byte to be
-     * written is the eight low-order bits of the argument b. The 24 high-order
-     * bits of b are ignored.
-     * @param b the byte to write
-     * @throws IOException if an I/O error occurs
-     */
-    @Override
-    public synchronized void write(int b) throws IOException {
-        ensureOpen();
-        mParent.ensureNotDone();
-        mArray.write(b);
-        if (mArray.size() == mMaxPacketSize) {
-            mParent.continueOperation(true, false);
-        }
-    }
-
-    @Override
-    public void write(byte[] buffer) throws IOException {
-        write(buffer, 0, buffer.length);
-    }
-
-    @Override
-    public synchronized void write(byte[] buffer, int offset, int count) throws IOException {
-        int offset1 = offset;
-        int remainLength = count;
-
-        if (buffer == null) {
-            throw new IOException("buffer is null");
-        }
-        if ((offset | count) < 0 || count > buffer.length - offset) {
-            throw new IndexOutOfBoundsException("index outof bound");
-        }
-
-        ensureOpen();
-        mParent.ensureNotDone();
-        while ((mArray.size() + remainLength) >= mMaxPacketSize) {
-            int bufferLeft = mMaxPacketSize - mArray.size();
-            mArray.write(buffer, offset1, bufferLeft);
-            offset1 += bufferLeft;
-            remainLength -= bufferLeft;
-            mParent.continueOperation(true, false);
-        }
-        if (remainLength > 0) {
-            mArray.write(buffer, offset1, remainLength);
-        }
-    }
-
-    /**
-     * Reads the bytes that have been written to this stream.
-     * @param size the size of the array to return
-     * @return the byte array that is written
-     */
-    public synchronized byte[] readBytes(int size) {
-        if (mArray.size() > 0) {
-            byte[] temp = mArray.toByteArray();
-            mArray.reset();
-            byte[] result = new byte[size];
-            System.arraycopy(temp, 0, result, 0, size);
-            if (temp.length != size) {
-                mArray.write(temp, size, temp.length - size);
-            }
-            return result;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Verifies that this stream is open
-     * @throws IOException if the stream is not open
-     */
-    private void ensureOpen() throws IOException {
-        mParent.ensureOpen();
-        if (!mOpen) {
-            throw new IOException("Output stream is closed");
-        }
-    }
-
-    /**
-     * Closes the output stream. If the input stream is already closed, do
-     * nothing.
-     * @throws IOException this will never happen
-     */
-    @Override
-    public void close() throws IOException {
-        mOpen = false;
-        mParent.streamClosed(false);
-    }
-
-    /**
-     * Determines if the connection is closed
-     * @return <code>true</code> if the connection is closed; <code>false</code>
-     *         if the connection is open
-     */
-    public boolean isClosed() {
-        return !mOpen;
-    }
-}
diff --git a/obex/javax/obex/ResponseCodes.java b/obex/javax/obex/ResponseCodes.java
deleted file mode 100644
index a2b9a37..0000000
--- a/obex/javax/obex/ResponseCodes.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-/**
- * The <code>ResponseCodes</code> class contains the list of valid response
- * codes a server may send to a client.
- * <P>
- * <STRONG>IMPORTANT NOTE</STRONG>
- * <P>
- * The values in this interface represent the values defined in the IrOBEX
- * specification, which is different with the HTTP specification.
- * <P>
- * <code>OBEX_DATABASE_FULL</code> and <code>OBEX_DATABASE_LOCKED</code> require
- * further description since they are not defined in HTTP. The server will send
- * an <code>OBEX_DATABASE_FULL</code> message when the client requests that
- * something be placed into a database but the database is full (cannot take
- * more data). <code>OBEX_DATABASE_LOCKED</code> will be returned when the
- * client wishes to access a database, database table, or database record that
- * has been locked.
- * @hide
- */
-public final class ResponseCodes {
-
-    /**
-     * Defines the OBEX CONTINUE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_CONTINUE</code> is 0x90 (144).
-     */
-    public static final int OBEX_HTTP_CONTINUE = 0x90;
-
-    /**
-     * Defines the OBEX SUCCESS response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_OK</code> is 0xA0 (160).
-     */
-    public static final int OBEX_HTTP_OK = 0xA0;
-
-    /**
-     * Defines the OBEX CREATED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_CREATED</code> is 0xA1 (161).
-     */
-    public static final int OBEX_HTTP_CREATED = 0xA1;
-
-    /**
-     * Defines the OBEX ACCEPTED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_ACCEPTED</code> is 0xA2 (162).
-     */
-    public static final int OBEX_HTTP_ACCEPTED = 0xA2;
-
-    /**
-     * Defines the OBEX NON-AUTHORITATIVE INFORMATION response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NOT_AUTHORITATIVE</code> is 0xA3 (163).
-     */
-    public static final int OBEX_HTTP_NOT_AUTHORITATIVE = 0xA3;
-
-    /**
-     * Defines the OBEX NO CONTENT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NO_CONTENT</code> is 0xA4 (164).
-     */
-    public static final int OBEX_HTTP_NO_CONTENT = 0xA4;
-
-    /**
-     * Defines the OBEX RESET CONTENT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_RESET</code> is 0xA5 (165).
-     */
-    public static final int OBEX_HTTP_RESET = 0xA5;
-
-    /**
-     * Defines the OBEX PARTIAL CONTENT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_PARTIAL</code> is 0xA6 (166).
-     */
-    public static final int OBEX_HTTP_PARTIAL = 0xA6;
-
-    /**
-     * Defines the OBEX MULTIPLE_CHOICES response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_MULT_CHOICE</code> is 0xB0 (176).
-     */
-    public static final int OBEX_HTTP_MULT_CHOICE = 0xB0;
-
-    /**
-     * Defines the OBEX MOVED PERMANENTLY response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_MOVED_PERM</code> is 0xB1 (177).
-     */
-    public static final int OBEX_HTTP_MOVED_PERM = 0xB1;
-
-    /**
-     * Defines the OBEX MOVED TEMPORARILY response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_MOVED_TEMP</code> is 0xB2 (178).
-     */
-    public static final int OBEX_HTTP_MOVED_TEMP = 0xB2;
-
-    /**
-     * Defines the OBEX SEE OTHER response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_SEE_OTHER</code> is 0xB3 (179).
-     */
-    public static final int OBEX_HTTP_SEE_OTHER = 0xB3;
-
-    /**
-     * Defines the OBEX NOT MODIFIED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NOT_MODIFIED</code> is 0xB4 (180).
-     */
-    public static final int OBEX_HTTP_NOT_MODIFIED = 0xB4;
-
-    /**
-     * Defines the OBEX USE PROXY response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_USE_PROXY</code> is 0xB5 (181).
-     */
-    public static final int OBEX_HTTP_USE_PROXY = 0xB5;
-
-    /**
-     * Defines the OBEX BAD REQUEST response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_BAD_REQUEST</code> is 0xC0 (192).
-     */
-    public static final int OBEX_HTTP_BAD_REQUEST = 0xC0;
-
-    /**
-     * Defines the OBEX UNAUTHORIZED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_UNAUTHORIZED</code> is 0xC1 (193).
-     */
-    public static final int OBEX_HTTP_UNAUTHORIZED = 0xC1;
-
-    /**
-     * Defines the OBEX PAYMENT REQUIRED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_PAYMENT_REQUIRED</code> is 0xC2 (194).
-     */
-    public static final int OBEX_HTTP_PAYMENT_REQUIRED = 0xC2;
-
-    /**
-     * Defines the OBEX FORBIDDEN response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_FORBIDDEN</code> is 0xC3 (195).
-     */
-    public static final int OBEX_HTTP_FORBIDDEN = 0xC3;
-
-    /**
-     * Defines the OBEX NOT FOUND response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NOT_FOUND</code> is 0xC4 (196).
-     */
-    public static final int OBEX_HTTP_NOT_FOUND = 0xC4;
-
-    /**
-     * Defines the OBEX METHOD NOT ALLOWED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_BAD_METHOD</code> is 0xC5 (197).
-     */
-    public static final int OBEX_HTTP_BAD_METHOD = 0xC5;
-
-    /**
-     * Defines the OBEX NOT ACCEPTABLE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NOT_ACCEPTABLE</code> is 0xC6 (198).
-     */
-    public static final int OBEX_HTTP_NOT_ACCEPTABLE = 0xC6;
-
-    /**
-     * Defines the OBEX PROXY AUTHENTICATION REQUIRED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_PROXY_AUTH</code> is 0xC7 (199).
-     */
-    public static final int OBEX_HTTP_PROXY_AUTH = 0xC7;
-
-    /**
-     * Defines the OBEX REQUEST TIME OUT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_TIMEOUT</code> is 0xC8 (200).
-     */
-    public static final int OBEX_HTTP_TIMEOUT = 0xC8;
-
-    /**
-     * Defines the OBEX METHOD CONFLICT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_CONFLICT</code> is 0xC9 (201).
-     */
-    public static final int OBEX_HTTP_CONFLICT = 0xC9;
-
-    /**
-     * Defines the OBEX METHOD GONE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_GONE</code> is 0xCA (202).
-     */
-    public static final int OBEX_HTTP_GONE = 0xCA;
-
-    /**
-     * Defines the OBEX METHOD LENGTH REQUIRED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_LENGTH_REQUIRED</code> is 0xCB (203).
-     */
-    public static final int OBEX_HTTP_LENGTH_REQUIRED = 0xCB;
-
-    /**
-     * Defines the OBEX PRECONDITION FAILED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_PRECON_FAILED</code> is 0xCC (204).
-     */
-    public static final int OBEX_HTTP_PRECON_FAILED = 0xCC;
-
-    /**
-     * Defines the OBEX REQUESTED ENTITY TOO LARGE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_ENTITY_TOO_LARGE</code> is 0xCD (205).
-     */
-    public static final int OBEX_HTTP_ENTITY_TOO_LARGE = 0xCD;
-
-    /**
-     * Defines the OBEX REQUESTED URL TOO LARGE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_REQ_TOO_LARGE</code> is 0xCE (206).
-     */
-    public static final int OBEX_HTTP_REQ_TOO_LARGE = 0xCE;
-
-    /**
-     * Defines the OBEX UNSUPPORTED MEDIA TYPE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_UNSUPPORTED_TYPE</code> is 0xCF (207).
-     */
-    public static final int OBEX_HTTP_UNSUPPORTED_TYPE = 0xCF;
-
-    /**
-     * Defines the OBEX INTERNAL SERVER ERROR response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_INTERNAL_ERROR</code> is 0xD0 (208).
-     */
-    public static final int OBEX_HTTP_INTERNAL_ERROR = 0xD0;
-
-    /**
-     * Defines the OBEX NOT IMPLEMENTED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_NOT_IMPLEMENTED</code> is 0xD1 (209).
-     */
-    public static final int OBEX_HTTP_NOT_IMPLEMENTED = 0xD1;
-
-    /**
-     * Defines the OBEX BAD GATEWAY response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_BAD_GATEWAY</code> is 0xD2 (210).
-     */
-    public static final int OBEX_HTTP_BAD_GATEWAY = 0xD2;
-
-    /**
-     * Defines the OBEX SERVICE UNAVAILABLE response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_UNAVAILABLE</code> is 0xD3 (211).
-     */
-    public static final int OBEX_HTTP_UNAVAILABLE = 0xD3;
-
-    /**
-     * Defines the OBEX GATEWAY TIMEOUT response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_GATEWAY_TIMEOUT</code> is 0xD4 (212).
-     */
-    public static final int OBEX_HTTP_GATEWAY_TIMEOUT = 0xD4;
-
-    /**
-     * Defines the OBEX HTTP VERSION NOT SUPPORTED response code.
-     * <P>
-     * The value of <code>OBEX_HTTP_VERSION</code> is 0xD5 (213).
-     */
-    public static final int OBEX_HTTP_VERSION = 0xD5;
-
-    /**
-     * Defines the OBEX DATABASE FULL response code.
-     * <P>
-     * The value of <code>OBEX_DATABASE_FULL</code> is 0xE0 (224).
-     */
-    public static final int OBEX_DATABASE_FULL = 0xE0;
-
-    /**
-     * Defines the OBEX DATABASE LOCKED response code.
-     * <P>
-     * The value of <code>OBEX_DATABASE_LOCKED</code> is 0xE1 (225).
-     */
-    public static final int OBEX_DATABASE_LOCKED = 0xE1;
-
-    /**
-     * Constructor does nothing.
-     */
-    private ResponseCodes() {
-    }
-}
diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java
deleted file mode 100644
index 15ea367..0000000
--- a/obex/javax/obex/ServerOperation.java
+++ /dev/null
@@ -1,861 +0,0 @@
-/* Copyright (c) 2015 The Android Open Source Project
- * Copyright (C) 2015 Samsung LSI
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.DataInputStream;
-import java.io.OutputStream;
-import java.io.DataOutputStream;
-import java.io.ByteArrayOutputStream;
-
-import android.util.Log;
-
-/**
- * This class implements the Operation interface for server side connections.
- * <P>
- * <STRONG>Request Codes</STRONG> There are four different request codes that
- * are in this class. 0x02 is a PUT request that signals that the request is not
- * complete and requires an additional OBEX packet. 0x82 is a PUT request that
- * says that request is complete. In this case, the server can begin sending the
- * response. The 0x03 is a GET request that signals that the request is not
- * finished. When the server receives a 0x83, the client is signaling the server
- * that it is done with its request. TODO: Extend the ClientOperation and reuse
- * the methods defined TODO: in that class.
- * @hide
- */
-public final class ServerOperation implements Operation, BaseStream {
-
-    private static final String TAG = "ServerOperation";
-
-    private static final boolean V = ObexHelper.VDBG; // Verbose debugging
-
-    public boolean isAborted;
-
-    public HeaderSet requestHeader;
-
-    public HeaderSet replyHeader;
-
-    public boolean finalBitSet;
-
-    private InputStream mInput;
-
-    private ServerSession mParent;
-
-    private int mMaxPacketLength;
-
-    private int mResponseSize;
-
-    private boolean mClosed;
-
-    private boolean mGetOperation;
-
-    private PrivateInputStream mPrivateInput;
-
-    private PrivateOutputStream mPrivateOutput;
-
-    private ObexTransport mTransport;
-
-    private boolean mPrivateOutputOpen;
-
-    private String mExceptionString;
-
-    private ServerRequestHandler mListener;
-
-    private boolean mRequestFinished;
-
-    private boolean mHasBody;
-
-    private boolean mSendBodyHeader = true;
-    // Assume SRM disabled - needs to be explicit
-    // enabled by client
-    private boolean mSrmEnabled = false;
-    // A latch - when triggered, there is not way back ;-)
-    private boolean mSrmActive = false;
-    // Set to true when a SRM enable response have been send
-    private boolean mSrmResponseSent = false;
-    // keep waiting until final-bit is received in request
-    // to handle the case where the SRM enable header is in
-    // a different OBEX packet than the SRMP header.
-    private boolean mSrmWaitingForRemote = true;
-    // Why should we wait? - currently not exposed to apps.
-    private boolean mSrmLocalWait = false;
-
-    /**
-     * Creates new ServerOperation
-     * @param p the parent that created this object
-     * @param in the input stream to read from
-     * @param out the output stream to write to
-     * @param request the initial request that was received from the client
-     * @param maxSize the max packet size that the client will accept
-     * @param listen the listener that is responding to the request
-     * @throws IOException if an IO error occurs
-     */
-    public ServerOperation(ServerSession p, InputStream in, int request, int maxSize,
-            ServerRequestHandler listen) throws IOException {
-
-        isAborted = false;
-        mParent = p;
-        mInput = in;
-        mMaxPacketLength = maxSize;
-        mClosed = false;
-        requestHeader = new HeaderSet();
-        replyHeader = new HeaderSet();
-        mPrivateInput = new PrivateInputStream(this);
-        mResponseSize = 3;
-        mListener = listen;
-        mRequestFinished = false;
-        mPrivateOutputOpen = false;
-        mHasBody = false;
-        ObexPacket packet;
-        mTransport = p.getTransport();
-
-        /*
-         * Determine if this is a PUT request
-         */
-        if ((request == ObexHelper.OBEX_OPCODE_PUT) ||
-                (request == ObexHelper.OBEX_OPCODE_PUT_FINAL)) {
-            /*
-             * It is a PUT request.
-             */
-            mGetOperation = false;
-
-            /*
-             * Determine if the final bit is set
-             */
-            if ((request & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) {
-                finalBitSet = false;
-            } else {
-                finalBitSet = true;
-                mRequestFinished = true;
-            }
-        } else if ((request == ObexHelper.OBEX_OPCODE_GET) ||
-                (request == ObexHelper.OBEX_OPCODE_GET_FINAL)) {
-            /*
-             * It is a GET request.
-             */
-            mGetOperation = true;
-
-            // For Get request, final bit set is decided by server side logic
-            finalBitSet = false;
-
-            if (request == ObexHelper.OBEX_OPCODE_GET_FINAL) {
-                mRequestFinished = true;
-            }
-        } else {
-            throw new IOException("ServerOperation can not handle such request");
-        }
-
-        packet = ObexPacket.read(request, mInput);
-
-        /*
-         * Determine if the packet length is larger than this device can receive
-         */
-        if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
-            mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
-            throw new IOException("Packet received was too large. Length: "
-                    + packet.mLength + " maxLength: " + ObexHelper.getMaxRxPacketSize(mTransport));
-        }
-
-        /*
-         * Determine if any headers were sent in the initial request
-         */
-        if (packet.mLength > 3) {
-            if(!handleObexPacket(packet)) {
-                return;
-            }
-            /* Don't Pre-Send continue when Remote requested for SRM
-             * Let the Application confirm.
-             */
-            if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
-                    + " not hasBody case: " + mHasBody);
-            if (!mHasBody && !mSrmEnabled) {
-                while ((!mGetOperation) && (!finalBitSet)) {
-                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-                    if (mPrivateInput.available() > 0) {
-                        break;
-                    }
-                }
-            }
-        }
-        /* Don't Pre-Send continue when Remote requested for SRM
-          * Let the Application confirm.
-          */
-        if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
-            + " not finalPacket: " + finalBitSet + " not GETOp Case: " + mGetOperation);
-        while ((!mSrmEnabled) && (!mGetOperation) && (!finalBitSet)
-                && (mPrivateInput.available() == 0)) {
-            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-            if (mPrivateInput.available() > 0) {
-                break;
-            }
-        }
-
-        // wait for get request finished !!!!
-        while (mGetOperation && !mRequestFinished) {
-            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-        }
-    }
-
-    /**
-     * Parse headers and update member variables
-     * @param packet the received obex packet
-     * @return false for failing authentication - and a OBEX_HTTP_UNAUTHORIZED
-     * response have been send. Else true.
-     * @throws IOException
-     */
-    private boolean handleObexPacket(ObexPacket packet) throws IOException {
-        byte[] body = updateRequestHeaders(packet);
-
-        if (body != null) {
-            mHasBody = true;
-        }
-        if (mListener.getConnectionId() != -1 && requestHeader.mConnectionID != null) {
-            mListener.setConnectionId(ObexHelper
-                    .convertToLong(requestHeader.mConnectionID));
-        } else {
-            mListener.setConnectionId(1);
-        }
-
-        if (requestHeader.mAuthResp != null) {
-            if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
-                mExceptionString = "Authentication Failed";
-                mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
-                mClosed = true;
-                requestHeader.mAuthResp = null;
-                return false;
-            }
-            requestHeader.mAuthResp = null;
-        }
-
-        if (requestHeader.mAuthChall != null) {
-            mParent.handleAuthChall(requestHeader);
-            // send the auhtResp to the client
-            replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
-            System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
-                    replyHeader.mAuthResp.length);
-            requestHeader.mAuthResp = null;
-            requestHeader.mAuthChall = null;
-        }
-
-        if (body != null) {
-            mPrivateInput.writeBytes(body, 1);
-        }
-        return true;
-    }
-
-    /**
-     * Update the request header set, and sniff on SRM headers to update local state.
-     * @param data the OBEX packet data
-     * @return any bytes in a body/end-of-body header returned by {@link ObexHelper.updateHeaderSet}
-     * @throws IOException
-     */
-    private byte[] updateRequestHeaders(ObexPacket packet) throws IOException {
-        byte[] body = null;
-        if (packet.mPayload != null) {
-            body = ObexHelper.updateHeaderSet(requestHeader, packet.mPayload);
-        }
-        Byte srmMode = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
-        if(mTransport.isSrmSupported() && srmMode != null
-                && srmMode == ObexHelper.OBEX_SRM_ENABLE) {
-            mSrmEnabled = true;
-            if(V) Log.d(TAG,"SRM is now ENABLED (but not active) for this operation");
-        }
-        checkForSrmWait(packet.mHeaderId);
-        if((!mSrmWaitingForRemote) && (mSrmEnabled)) {
-            if(V) Log.d(TAG,"SRM is now ACTIVE for this operation");
-            mSrmActive = true;
-        }
-        return body;
-    }
-
-    /**
-     * Call this only when a complete request have been received.
-     * (This is not optimal, but the current design is not really suited to
-     * the way SRM is specified.)
-     */
-    private void checkForSrmWait(int headerId){
-        if (mSrmEnabled && (headerId == ObexHelper.OBEX_OPCODE_GET
-                || headerId == ObexHelper.OBEX_OPCODE_GET_FINAL
-                || headerId == ObexHelper.OBEX_OPCODE_PUT)) {
-            try {
-                mSrmWaitingForRemote = false;
-                Byte srmp = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
-                if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) {
-                    mSrmWaitingForRemote = true;
-                    // Clear the wait header, as the absents of the header when the final bit is set
-                    // indicates don't wait.
-                    requestHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
-                }
-            } catch (IOException e) {if(V){Log.w(TAG,"Exception while extracting header",e);}}
-        }
-    }
-
-    public boolean isValidBody() {
-        return mHasBody;
-    }
-
-    /**
-     * Determines if the operation should continue or should wait. If it should
-     * continue, this method will continue the operation.
-     * @param sendEmpty if <code>true</code> then this will continue the
-     *        operation even if no headers will be sent; if <code>false</code>
-     *        then this method will only continue the operation if there are
-     *        headers to send
-     * @param inStream if<code>true</code> the stream is input stream, otherwise
-     *        output stream
-     * @return <code>true</code> if the operation was completed;
-     *         <code>false</code> if no operation took place
-     */
-    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
-            throws IOException {
-        if (!mGetOperation) {
-            if (!finalBitSet) {
-                if (sendEmpty) {
-                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-                    return true;
-                } else {
-                    if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) {
-                        sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-            } else {
-                return false;
-            }
-        } else {
-            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-            return true;
-        }
-    }
-
-    /**
-     * Sends a reply to the client. If the reply is a OBEX_HTTP_CONTINUE, it
-     * will wait for a response from the client before ending unless SRM is active.
-     * @param type the response code to send back to the client
-     * @return <code>true</code> if the final bit was not set on the reply;
-     *         <code>false</code> if no reply was received because the operation
-     *         ended, an abort was received, the final bit was set in the
-     *         reply or SRM is active.
-     * @throws IOException if an IO error occurs
-     */
-    public synchronized boolean sendReply(int type) throws IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        boolean skipSend = false;
-        boolean skipReceive = false;
-        boolean srmRespSendPending = false;
-
-        long id = mListener.getConnectionId();
-        if (id == -1) {
-            replyHeader.mConnectionID = null;
-        } else {
-            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
-        }
-
-        if(mSrmEnabled && !mSrmResponseSent) {
-            // As we are not ensured that the SRM enable is in the first OBEX packet
-            // We must check for each reply.
-            if(V)Log.v(TAG, "mSrmEnabled==true, sending SRM enable response.");
-            replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRM_ENABLE);
-            srmRespSendPending = true;
-        }
-
-        if(mSrmEnabled && !mGetOperation && mSrmLocalWait) {
-            replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRMP_WAIT);
-        }
-
-        byte[] headerArray = ObexHelper.createHeader(replyHeader, true); // This clears the headers
-        int bodyLength = -1;
-        int orginalBodyLength = -1;
-
-        if (mPrivateOutput != null) {
-            bodyLength = mPrivateOutput.size();
-            orginalBodyLength = bodyLength;
-        }
-
-        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) {
-
-            int end = 0;
-            int start = 0;
-
-            while (end != headerArray.length) {
-                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketLength
-                        - ObexHelper.BASE_PACKET_LENGTH);
-                if (end == -1) {
-
-                    mClosed = true;
-
-                    if (mPrivateInput != null) {
-                        mPrivateInput.close();
-                    }
-
-                    if (mPrivateOutput != null) {
-                        mPrivateOutput.close();
-                    }
-                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
-                    throw new IOException("OBEX Packet exceeds max packet size");
-                }
-                byte[] sendHeader = new byte[end - start];
-                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
-
-                mParent.sendResponse(type, sendHeader);
-                start = end;
-            }
-
-            if (bodyLength > 0) {
-                return true;
-            } else {
-                return false;
-            }
-
-        } else {
-            out.write(headerArray);
-        }
-
-        // For Get operation: if response code is OBEX_HTTP_OK, then this is the
-        // last packet; so set finalBitSet to true.
-        if (mGetOperation && type == ResponseCodes.OBEX_HTTP_OK) {
-            finalBitSet = true;
-        }
-
-        if(mSrmActive) {
-            if(!mGetOperation && type == ResponseCodes.OBEX_HTTP_CONTINUE &&
-                    mSrmResponseSent == true) {
-                // we are in the middle of a SRM PUT operation, don't send a continue.
-                skipSend = true;
-            } else if(mGetOperation && mRequestFinished == false && mSrmResponseSent == true) {
-                // We are still receiving the get request, receive, but don't send continue.
-                skipSend = true;
-            } else if(mGetOperation && mRequestFinished == true) {
-                // All done receiving the GET request, send data to the client, without
-                // expecting a continue.
-                skipReceive = true;
-            }
-            if(V)Log.v(TAG, "type==" + type + " skipSend==" + skipSend
-                    + " skipReceive==" + skipReceive);
-        }
-        if(srmRespSendPending) {
-            if(V)Log.v(TAG,
-                    "SRM Enabled (srmRespSendPending == true)- sending SRM Enable response");
-            mSrmResponseSent = true;
-        }
-
-        if ((finalBitSet) || (headerArray.length < (mMaxPacketLength - 20))) {
-            if (bodyLength > 0) {
-                /*
-                 * Determine if I can send the whole body or just part of
-                 * the body.  Remember that there is the 3 bytes for the
-                 * response message and 3 bytes for the header ID and length
-                 */
-                if (bodyLength > (mMaxPacketLength - headerArray.length - 6)) {
-                    bodyLength = mMaxPacketLength - headerArray.length - 6;
-                }
-
-                byte[] body = mPrivateOutput.readBytes(bodyLength);
-
-                /*
-                 * Since this is a put request if the final bit is set or
-                 * the output stream is closed we need to send the 0x49
-                 * (End of Body) otherwise, we need to send 0x48 (Body)
-                 */
-                if ((finalBitSet) || (mPrivateOutput.isClosed())) {
-                    if(mSendBodyHeader == true) {
-                        out.write(0x49);
-                        bodyLength += 3;
-                        out.write((byte)(bodyLength >> 8));
-                        out.write((byte)bodyLength);
-                        out.write(body);
-                    }
-                } else {
-                    if(mSendBodyHeader == true) {
-                    out.write(0x48);
-                    bodyLength += 3;
-                    out.write((byte)(bodyLength >> 8));
-                    out.write((byte)bodyLength);
-                    out.write(body);
-                    }
-                }
-
-            }
-        }
-
-        if ((finalBitSet) && (type == ResponseCodes.OBEX_HTTP_OK) && (orginalBodyLength <= 0)) {
-            if(mSendBodyHeader) {
-                out.write(0x49);
-                orginalBodyLength = 3;
-                out.write((byte)(orginalBodyLength >> 8));
-                out.write((byte)orginalBodyLength);
-            }
-        }
-
-        if(skipSend == false) {
-            mResponseSize = 3;
-            mParent.sendResponse(type, out.toByteArray());
-        }
-
-        if (type == ResponseCodes.OBEX_HTTP_CONTINUE) {
-
-            if(mGetOperation && skipReceive) {
-                // Here we need to check for and handle abort (throw an exception).
-                // Any other signal received should be discarded silently (only on server side)
-                checkSrmRemoteAbort();
-            } else {
-                // Receive and handle data (only send reply if !skipSend)
-                // Read a complete OBEX Packet
-                ObexPacket packet = ObexPacket.read(mInput);
-
-                int headerId = packet.mHeaderId;
-                if ((headerId != ObexHelper.OBEX_OPCODE_PUT)
-                        && (headerId != ObexHelper.OBEX_OPCODE_PUT_FINAL)
-                        && (headerId != ObexHelper.OBEX_OPCODE_GET)
-                        && (headerId != ObexHelper.OBEX_OPCODE_GET_FINAL)) {
-
-                    /*
-                     * Determine if an ABORT was sent as the reply
-                     */
-                    if (headerId == ObexHelper.OBEX_OPCODE_ABORT) {
-                        handleRemoteAbort();
-                    } else {
-                        // TODO:shall we send this if it occurs during SRM? Errata on the subject
-                        mParent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
-                        mClosed = true;
-                        mExceptionString = "Bad Request Received";
-                        throw new IOException("Bad Request Received");
-                    }
-                } else {
-
-                    if ((headerId == ObexHelper.OBEX_OPCODE_PUT_FINAL)) {
-                        finalBitSet = true;
-                    } else if (headerId == ObexHelper.OBEX_OPCODE_GET_FINAL) {
-                        mRequestFinished = true;
-                    }
-
-                    /*
-                     * Determine if the packet length is larger than the negotiated packet size
-                     */
-                    if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
-                        mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
-                        throw new IOException("Packet received was too large");
-                    }
-
-                    /*
-                     * Determine if any headers were sent in the initial request
-                     */
-                    if (packet.mLength > 3 || (mSrmEnabled && packet.mLength == 3)) {
-                        if(handleObexPacket(packet) == false) {
-                            return false;
-                        }
-                    }
-                }
-
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * This method will look for an abort from the peer during a SRM transfer.
-     * The function will not block if no data has been received from the remote device.
-     * If data have been received, the function will block while reading the incoming
-     * OBEX package.
-     * An Abort request will be handled, and cause an IOException("Abort Received").
-     * Other messages will be discarded silently as per GOEP specification.
-     * @throws IOException if an abort request have been received.
-     * TODO: I think this is an error in the specification. If we discard other messages,
-     *       the peer device will most likely stall, as it will not receive the expected
-     *       response for the message...
-     *       I'm not sure how to understand "Receipt of invalid or unexpected SRM or SRMP
-     *       header values shall be ignored by the receiving device."
-     *       If any signal is received during an active SRM transfer it is unexpected regardless
-     *       whether or not it contains SRM/SRMP headers...
-     */
-    private void checkSrmRemoteAbort() throws IOException {
-        if(mInput.available() > 0) {
-            ObexPacket packet = ObexPacket.read(mInput);
-            /*
-             * Determine if an ABORT was sent as the reply
-             */
-            if (packet.mHeaderId == ObexHelper.OBEX_OPCODE_ABORT) {
-                handleRemoteAbort();
-            } else {
-                // TODO: should we throw an exception here anyway? - don't see how to
-                //       ignore SRM/SRMP headers without ignoring the complete signal
-                //       (in this particular case).
-                Log.w(TAG, "Received unexpected request from client - discarding...\n"
-                        + "   headerId: " + packet.mHeaderId + " length: " + packet.mLength);
-            }
-        }
-    }
-
-    private void handleRemoteAbort() throws IOException {
-        /* TODO: To increase the speed of the abort operation in SRM, we need
-         *       to be able to flush the L2CAP queue for the PSM in use.
-         *       This could be implemented by introducing a control
-         *       message to be send over the socket, that in the abort case
-         *       could carry a flush command. */
-        mParent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null);
-        mClosed = true;
-        isAborted = true;
-        mExceptionString = "Abort Received";
-        throw new IOException("Abort Received");
-    }
-
-    /**
-     * Sends an ABORT message to the server. By calling this method, the
-     * corresponding input and output streams will be closed along with this
-     * object.
-     * @throws IOException if the transaction has already ended or if an OBEX
-     *         server called this method
-     */
-    public void abort() throws IOException {
-        throw new IOException("Called from a server");
-    }
-
-    /**
-     * Returns the headers that have been received during the operation.
-     * Modifying the object returned has no effect on the headers that are sent
-     * or retrieved.
-     * @return the headers received during this <code>Operation</code>
-     * @throws IOException if this <code>Operation</code> has been closed
-     */
-    public HeaderSet getReceivedHeader() throws IOException {
-        ensureOpen();
-        return requestHeader;
-    }
-
-    /**
-     * Specifies the headers that should be sent in the next OBEX message that
-     * is sent.
-     * @param headers the headers to send in the next message
-     * @throws IOException if this <code>Operation</code> has been closed or the
-     *         transaction has ended and no further messages will be exchanged
-     * @throws IllegalArgumentException if <code>headers</code> was not created
-     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
-     */
-    public void sendHeaders(HeaderSet headers) throws IOException {
-        ensureOpen();
-
-        if (headers == null) {
-            throw new IOException("Headers may not be null");
-        }
-
-        int[] headerList = headers.getHeaderList();
-        if (headerList != null) {
-            for (int i = 0; i < headerList.length; i++) {
-                replyHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
-            }
-
-        }
-    }
-
-    /**
-     * Retrieves the response code retrieved from the server. Response codes are
-     * defined in the <code>ResponseCodes</code> interface.
-     * @return the response code retrieved from the server
-     * @throws IOException if an error occurred in the transport layer during
-     *         the transaction; if this method is called on a
-     *         <code>HeaderSet</code> object created by calling
-     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
-     *         object; if this is called from a server
-     */
-    public int getResponseCode() throws IOException {
-        throw new IOException("Called from a server");
-    }
-
-    /**
-     * Always returns <code>null</code>
-     * @return <code>null</code>
-     */
-    public String getEncoding() {
-        return null;
-    }
-
-    /**
-     * Returns the type of content that the resource connected to is providing.
-     * E.g. if the connection is via HTTP, then the value of the content-type
-     * header field is returned.
-     * @return the content type of the resource that the URL references, or
-     *         <code>null</code> if not known
-     */
-    public String getType() {
-        try {
-            return (String)requestHeader.getHeader(HeaderSet.TYPE);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the length of the content which is being provided. E.g. if the
-     * connection is via HTTP, then the value of the content-length header field
-     * is returned.
-     * @return the content length of the resource that this connection's URL
-     *         references, or -1 if the content length is not known
-     */
-    public long getLength() {
-        try {
-            Long temp = (Long)requestHeader.getHeader(HeaderSet.LENGTH);
-
-            if (temp == null) {
-                return -1;
-            } else {
-                return temp.longValue();
-            }
-        } catch (IOException e) {
-            return -1;
-        }
-    }
-
-    public int getMaxPacketSize() {
-        return mMaxPacketLength - 6 - getHeaderLength();
-    }
-
-    public int getHeaderLength() {
-        long id = mListener.getConnectionId();
-        if (id == -1) {
-            replyHeader.mConnectionID = null;
-        } else {
-            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
-        }
-
-        byte[] headerArray = ObexHelper.createHeader(replyHeader, false);
-
-        return headerArray.length;
-    }
-
-    /**
-     * Open and return an input stream for a connection.
-     * @return an input stream
-     * @throws IOException if an I/O error occurs
-     */
-    public InputStream openInputStream() throws IOException {
-        ensureOpen();
-        return mPrivateInput;
-    }
-
-    /**
-     * Open and return a data input stream for a connection.
-     * @return an input stream
-     * @throws IOException if an I/O error occurs
-     */
-    public DataInputStream openDataInputStream() throws IOException {
-        return new DataInputStream(openInputStream());
-    }
-
-    /**
-     * Open and return an output stream for a connection.
-     * @return an output stream
-     * @throws IOException if an I/O error occurs
-     */
-    public OutputStream openOutputStream() throws IOException {
-        ensureOpen();
-
-        if (mPrivateOutputOpen) {
-            throw new IOException("no more input streams available, stream already opened");
-        }
-
-        if (!mRequestFinished) {
-            throw new IOException("no  output streams available ,request not finished");
-        }
-
-        if (mPrivateOutput == null) {
-            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
-        }
-        mPrivateOutputOpen = true;
-        return mPrivateOutput;
-    }
-
-    /**
-     * Open and return a data output stream for a connection.
-     * @return an output stream
-     * @throws IOException if an I/O error occurs
-     */
-    public DataOutputStream openDataOutputStream() throws IOException {
-        return new DataOutputStream(openOutputStream());
-    }
-
-    /**
-     * Closes the connection and ends the transaction
-     * @throws IOException if the operation has already ended or is closed
-     */
-    public void close() throws IOException {
-        ensureOpen();
-        mClosed = true;
-    }
-
-    /**
-     * Verifies that the connection is open and no exceptions should be thrown.
-     * @throws IOException if an exception needs to be thrown
-     */
-    public void ensureOpen() throws IOException {
-        if (mExceptionString != null) {
-            throw new IOException(mExceptionString);
-        }
-        if (mClosed) {
-            throw new IOException("Operation has already ended");
-        }
-    }
-
-    /**
-     * Verifies that additional information may be sent. In other words, the
-     * operation is not done.
-     * <P>
-     * Included to implement the BaseStream interface only. It does not do
-     * anything on the server side since the operation of the Operation object
-     * is not done until after the handler returns from its method.
-     * @throws IOException if the operation is completed
-     */
-    public void ensureNotDone() throws IOException {
-    }
-
-    /**
-     * Called when the output or input stream is closed. It does not do anything
-     * on the server side since the operation of the Operation object is not
-     * done until after the handler returns from its method.
-     * @param inStream <code>true</code> if the input stream is closed;
-     *        <code>false</code> if the output stream is closed
-     * @throws IOException if an IO error occurs
-     */
-    public void streamClosed(boolean inStream) throws IOException {
-
-    }
-
-    public void noBodyHeader(){
-        mSendBodyHeader = false;
-    }
-}
diff --git a/obex/javax/obex/ServerRequestHandler.java b/obex/javax/obex/ServerRequestHandler.java
deleted file mode 100644
index 09cbc2c..0000000
--- a/obex/javax/obex/ServerRequestHandler.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-/**
- * The <code>ServerRequestHandler</code> class defines an event listener that
- * will respond to OBEX requests made to the server.
- * <P>
- * The <code>onConnect()</code>, <code>onSetPath()</code>,
- * <code>onDelete()</code>, <code>onGet()</code>, and <code>onPut()</code>
- * methods may return any response code defined in the
- * <code>ResponseCodes</code> class except for <code>OBEX_HTTP_CONTINUE</code>.
- * If <code>OBEX_HTTP_CONTINUE</code> or a value not defined in the
- * <code>ResponseCodes</code> class is returned, the server implementation will
- * send an <code>OBEX_HTTP_INTERNAL_ERROR</code> response to the client.
- * <P>
- * <STRONG>Connection ID and Target Headers</STRONG>
- * <P>
- * According to the IrOBEX specification, a packet may not contain a Connection
- * ID and Target header. Since the Connection ID header is managed by the
- * implementation, it will not send a Connection ID header, if a Connection ID
- * was specified, in a packet that has a Target header. In other words, if an
- * application adds a Target header to a <code>HeaderSet</code> object used in
- * an OBEX operation and a Connection ID was specified, no Connection ID will be
- * sent in the packet containing the Target header.
- * <P>
- * <STRONG>CREATE-EMPTY Requests</STRONG>
- * <P>
- * A CREATE-EMPTY request allows clients to create empty objects on the server.
- * When a CREATE-EMPTY request is received, the <code>onPut()</code> method will
- * be called by the implementation. To differentiate between a normal PUT
- * request and a CREATE-EMPTY request, an application must open the
- * <code>InputStream</code> from the <code>Operation</code> object passed to the
- * <code>onPut()</code> method. For a PUT request, the application will be able
- * to read Body data from this <code>InputStream</code>. For a CREATE-EMPTY
- * request, there will be no Body data to read. Therefore, a call to
- * <code>InputStream.read()</code> will return -1.
- * @hide
- */
-public class ServerRequestHandler {
-
-    private long mConnectionId;
-
-    /**
-     * Creates a <code>ServerRequestHandler</code>.
-     */
-    protected ServerRequestHandler() {
-        /*
-         * A connection ID of -1 implies there is no conenction ID
-         */
-        mConnectionId = -1;
-    }
-
-    /**
-     * Sets the connection ID header to include in the reply packets.
-     * @param connectionId the connection ID to use; -1 if no connection ID
-     *        should be sent
-     * @throws IllegalArgumentException if <code>id</code> is not in the range
-     *         -1 to 2<sup>32</sup>-1
-     */
-    public void setConnectionId(final long connectionId) {
-        if ((connectionId < -1) || (connectionId > 0xFFFFFFFFL)) {
-            throw new IllegalArgumentException("Illegal Connection ID");
-        }
-        mConnectionId = connectionId;
-    }
-
-    /**
-     * Retrieves the connection ID that is being used in the present connection.
-     * This method will return -1 if no connection ID is being used.
-     * @return the connection id being used or -1 if no connection ID is being
-     *         used
-     */
-    public long getConnectionId() {
-        return mConnectionId;
-    }
-
-    /**
-     * Called when a CONNECT request is received.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * <code>onConnect()</code> will always return an <code>OBEX_HTTP_OK</code>
-     * response code.
-     * <P>
-     * The headers received in the request can be retrieved from the
-     * <code>request</code> argument. The headers that should be sent in the
-     * reply must be specified in the <code>reply</code> argument.
-     * @param request contains the headers sent by the client;
-     *        <code>request</code> will never be <code>null</code>
-     * @param reply the headers that should be sent in the reply;
-     *        <code>reply</code> will never be <code>null</code>
-     * @return a response code defined in <code>ResponseCodes</code> that will
-     *         be returned to the client; if an invalid response code is
-     *         provided, the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code
-     *         will be used
-     */
-    public int onConnect(HeaderSet request, HeaderSet reply) {
-        return ResponseCodes.OBEX_HTTP_OK;
-    }
-
-    /**
-     * Called when a DISCONNECT request is received.
-     * <P>
-     * The headers received in the request can be retrieved from the
-     * <code>request</code> argument. The headers that should be sent in the
-     * reply must be specified in the <code>reply</code> argument.
-     * @param request contains the headers sent by the client;
-     *        <code>request</code> will never be <code>null</code>
-     * @param reply the headers that should be sent in the reply;
-     *        <code>reply</code> will never be <code>null</code>
-     */
-    public void onDisconnect(HeaderSet request, HeaderSet reply) {
-    }
-
-    /**
-     * Called when a SETPATH request is received.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * <code>onSetPath()</code> will always return an
-     * <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
-     * <P>
-     * The headers received in the request can be retrieved from the
-     * <code>request</code> argument. The headers that should be sent in the
-     * reply must be specified in the <code>reply</code> argument.
-     * @param request contains the headers sent by the client;
-     *        <code>request</code> will never be <code>null</code>
-     * @param reply the headers that should be sent in the reply;
-     *        <code>reply</code> will never be <code>null</code>
-     * @param backup <code>true</code> if the client requests that the server
-     *        back up one directory before changing to the path described by
-     *        <code>name</code>; <code>false</code> to apply the request to the
-     *        present path
-     * @param create <code>true</code> if the path should be created if it does
-     *        not already exist; <code>false</code> if the path should not be
-     *        created if it does not exist and an error code should be returned
-     * @return a response code defined in <code>ResponseCodes</code> that will
-     *         be returned to the client; if an invalid response code is
-     *         provided, the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code
-     *         will be used
-     */
-    public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) {
-
-        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
-    }
-
-    /**
-     * Called when a DELETE request is received.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * <code>onDelete()</code> will always return an
-     * <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
-     * <P>
-     * The headers received in the request can be retrieved from the
-     * <code>request</code> argument. The headers that should be sent in the
-     * reply must be specified in the <code>reply</code> argument.
-     * @param request contains the headers sent by the client;
-     *        <code>request</code> will never be <code>null</code>
-     * @param reply the headers that should be sent in the reply;
-     *        <code>reply</code> will never be <code>null</code>
-     * @return a response code defined in <code>ResponseCodes</code> that will
-     *         be returned to the client; if an invalid response code is
-     *         provided, the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code
-     *         will be used
-     */
-    public int onDelete(HeaderSet request, HeaderSet reply) {
-        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
-    }
-
-    /**
-     * Called when a ABORT request is received.
-     */
-    public int onAbort(HeaderSet request, HeaderSet reply) {
-        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
-    }
-
-    /**
-     * Called when a PUT request is received.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * <code>onPut()</code> will always return an
-     * <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
-     * <P>
-     * If an ABORT request is received during the processing of a PUT request,
-     * <code>op</code> will be closed by the implementation.
-     * @param operation contains the headers sent by the client and allows new
-     *        headers to be sent in the reply; <code>op</code> will never be
-     *        <code>null</code>
-     * @return a response code defined in <code>ResponseCodes</code> that will
-     *         be returned to the client; if an invalid response code is
-     *         provided, the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code
-     *         will be used
-     */
-    public int onPut(Operation operation) {
-        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
-    }
-
-    /**
-     * Called when a GET request is received.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * <code>onGet()</code> will always return an
-     * <code>OBEX_HTTP_NOT_IMPLEMENTED</code> response code.
-     * <P>
-     * If an ABORT request is received during the processing of a GET request,
-     * <code>op</code> will be closed by the implementation.
-     * @param operation contains the headers sent by the client and allows new
-     *        headers to be sent in the reply; <code>op</code> will never be
-     *        <code>null</code>
-     * @return a response code defined in <code>ResponseCodes</code> that will
-     *         be returned to the client; if an invalid response code is
-     *         provided, the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code
-     *         will be used
-     */
-    public int onGet(Operation operation) {
-        return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
-    }
-
-    /**
-     * Called when this object attempts to authenticate a client and the
-     * authentication request fails because the response digest in the
-     * authentication response header was wrong.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * this method will do nothing.
-     * @param userName the user name returned in the authentication response;
-     *        <code>null</code> if no user name was provided in the response
-     */
-    public void onAuthenticationFailure(byte[] userName) {
-    }
-
-    /**
-     * Called by ServerSession to update the status of current transaction
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * this method will do nothing.
-     */
-    public void updateStatus(String message) {
-    }
-
-    /**
-     * Called when session is closed.
-     * <P>
-     * If this method is not implemented by the class that extends this class,
-     * this method will do nothing.
-     */
-    public void onClose() {
-    }
-
-    /**
-     * Override to add Single Response Mode support - e.g. if the supplied
-     * transport is l2cap.
-     * @return True if SRM is supported, else False
-     */
-    public boolean isSrmSupported() {
-        return false;
-    }
-}
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
deleted file mode 100644
index dbfeefd..0000000
--- a/obex/javax/obex/ServerSession.java
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Copyright (c) 2015 Samsung LSI
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import android.util.Log;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * This class in an implementation of the OBEX ServerSession.
- * @hide
- */
-public final class ServerSession extends ObexSession implements Runnable {
-
-    private static final String TAG = "Obex ServerSession";
-    private static final boolean V = ObexHelper.VDBG;
-
-    private ObexTransport mTransport;
-
-    private InputStream mInput;
-
-    private OutputStream mOutput;
-
-    private ServerRequestHandler mListener;
-
-    private Thread mProcessThread;
-
-    private int mMaxPacketLength;
-
-    private boolean mClosed;
-
-    /**
-     * Creates new ServerSession.
-     * @param trans the connection to the client
-     * @param handler the event listener that will process requests
-     * @param auth the authenticator to use with this connection
-     * @throws IOException if an error occurred while opening the input and
-     *         output streams
-     */
-    public ServerSession(ObexTransport trans, ServerRequestHandler handler, Authenticator auth)
-            throws IOException {
-        mAuthenticator = auth;
-        mTransport = trans;
-        mInput = mTransport.openInputStream();
-        mOutput = mTransport.openOutputStream();
-        mListener = handler;
-        mMaxPacketLength = 256;
-
-        mClosed = false;
-        mProcessThread = new Thread(this);
-        mProcessThread.start();
-    }
-
-    /**
-     * Processes requests made to the server and forwards them to the
-     * appropriate event listener.
-     */
-    public void run() {
-        try {
-
-            boolean done = false;
-            while (!done && !mClosed) {
-                if(V) Log.v(TAG, "Waiting for incoming request...");
-                int requestType = mInput.read();
-                if(V) Log.v(TAG, "Read request: " + requestType);
-                switch (requestType) {
-                    case ObexHelper.OBEX_OPCODE_CONNECT:
-                        handleConnectRequest();
-                        break;
-
-                    case ObexHelper.OBEX_OPCODE_DISCONNECT:
-                        handleDisconnectRequest();
-                        break;
-
-                    case ObexHelper.OBEX_OPCODE_GET:
-                    case ObexHelper.OBEX_OPCODE_GET_FINAL:
-                        handleGetRequest(requestType);
-                        break;
-
-                    case ObexHelper.OBEX_OPCODE_PUT:
-                    case ObexHelper.OBEX_OPCODE_PUT_FINAL:
-                        handlePutRequest(requestType);
-                        break;
-
-                    case ObexHelper.OBEX_OPCODE_SETPATH:
-                        handleSetPathRequest();
-                        break;
-                    case ObexHelper.OBEX_OPCODE_ABORT:
-                        handleAbortRequest();
-                        break;
-
-                    case -1:
-                        done = true;
-                        break;
-
-                    default:
-
-                        /*
-                         * Received a request type that is not recognized so I am
-                         * just going to read the packet and send a not implemented
-                         * to the client
-                         */
-                        int length = mInput.read();
-                        length = (length << 8) + mInput.read();
-                        for (int i = 3; i < length; i++) {
-                            mInput.read();
-                        }
-                        sendResponse(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null);
-                }
-            }
-
-        } catch (NullPointerException e) {
-            Log.d(TAG, "Exception occured - ignoring", e);
-        } catch (Exception e) {
-            Log.d(TAG, "Exception occured - ignoring", e);
-        }
-        close();
-    }
-
-    /**
-     * Handles a ABORT request from a client. This method will read the rest of
-     * the request from the client. Assuming the request is valid, it will
-     * create a <code>HeaderSet</code> object to pass to the
-     * <code>ServerRequestHandler</code> object. After the handler processes the
-     * request, this method will create a reply message to send to the server.
-     *
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handleAbortRequest() throws IOException {
-        int code = ResponseCodes.OBEX_HTTP_OK;
-        HeaderSet request = new HeaderSet();
-        HeaderSet reply = new HeaderSet();
-
-        int length = mInput.read();
-        length = (length << 8) + mInput.read();
-        if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
-            code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
-        } else {
-            for (int i = 3; i < length; i++) {
-                mInput.read();
-            }
-            code = mListener.onAbort(request, reply);
-            Log.v(TAG, "onAbort request handler return value- " + code);
-            code = validateResponseCode(code);
-        }
-        sendResponse(code, null);
-    }
-
-    /**
-     * Handles a PUT request from a client. This method will provide a
-     * <code>ServerOperation</code> object to the request handler. The
-     * <code>ServerOperation</code> object will handle the rest of the request.
-     * It will also send replies and receive requests until the final reply
-     * should be sent. When the final reply should be sent, this method will get
-     * the response code to use and send the reply. The
-     * <code>ServerOperation</code> object will always reply with a
-     * OBEX_HTTP_CONTINUE reply. It will only reply if further information is
-     * needed.
-     * @param type the type of request received; either 0x02 or 0x82
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handlePutRequest(int type) throws IOException {
-        ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
-        try {
-            int response = -1;
-
-            if ((op.finalBitSet) && !op.isValidBody()) {
-                response = validateResponseCode(mListener
-                        .onDelete(op.requestHeader, op.replyHeader));
-            } else {
-                response = validateResponseCode(mListener.onPut(op));
-            }
-            if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) {
-                op.sendReply(response);
-            } else if (!op.isAborted) {
-                // wait for the final bit
-                while (!op.finalBitSet) {
-                    op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
-                }
-                op.sendReply(response);
-            }
-        } catch (Exception e) {
-            /*To fix bugs in aborted cases,
-             *(client abort file transfer prior to the last packet which has the end of body header,
-             *internal error should not be sent because server has already replied with
-             *OK response in "sendReply")
-             */
-            if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
-            if (!op.isAborted) {
-                sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
-            }
-        }
-    }
-
-    /**
-     * Handles a GET request from a client. This method will provide a
-     * <code>ServerOperation</code> object to the request handler. The
-     * <code>ServerOperation</code> object will handle the rest of the request.
-     * It will also send replies and receive requests until the final reply
-     * should be sent. When the final reply should be sent, this method will get
-     * the response code to use and send the reply. The
-     * <code>ServerOperation</code> object will always reply with a
-     * OBEX_HTTP_CONTINUE reply. It will only reply if further information is
-     * needed.
-     * @param type the type of request received; either 0x03 or 0x83
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handleGetRequest(int type) throws IOException {
-        ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
-        try {
-            int response = validateResponseCode(mListener.onGet(op));
-
-            if (!op.isAborted) {
-                op.sendReply(response);
-            }
-        } catch (Exception e) {
-            if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
-            sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
-        }
-    }
-
-    /**
-     * Send standard response.
-     * @param code the response code to send
-     * @param header the headers to include in the response
-     * @throws IOException if an IO error occurs
-     */
-    public void sendResponse(int code, byte[] header) throws IOException {
-        int totalLength = 3;
-        byte[] data = null;
-        OutputStream op = mOutput;
-        if (op == null) {
-            return;
-        }
-
-        if (header != null) {
-            totalLength += header.length;
-            data = new byte[totalLength];
-            data[0] = (byte)code;
-            data[1] = (byte)(totalLength >> 8);
-            data[2] = (byte)totalLength;
-            System.arraycopy(header, 0, data, 3, header.length);
-        } else {
-            data = new byte[totalLength];
-            data[0] = (byte)code;
-            data[1] = (byte)0x00;
-            data[2] = (byte)totalLength;
-        }
-        op.write(data);
-        op.flush(); // TODO: Do we need to flush?
-    }
-
-    /**
-     * Handles a SETPATH request from a client. This method will read the rest
-     * of the request from the client. Assuming the request is valid, it will
-     * create a <code>HeaderSet</code> object to pass to the
-     * <code>ServerRequestHandler</code> object. After the handler processes the
-     * request, this method will create a reply message to send to the server
-     * with the response code provided.
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handleSetPathRequest() throws IOException {
-        int length;
-        int flags;
-        @SuppressWarnings("unused")
-        int constants;
-        int totalLength = 3;
-        byte[] head = null;
-        int code = -1;
-        int bytesReceived;
-        HeaderSet request = new HeaderSet();
-        HeaderSet reply = new HeaderSet();
-
-        length = mInput.read();
-        length = (length << 8) + mInput.read();
-        flags = mInput.read();
-        constants = mInput.read();
-
-        if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
-            code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
-            totalLength = 3;
-        } else {
-            if (length > 5) {
-                byte[] headers = new byte[length - 5];
-                bytesReceived = mInput.read(headers);
-
-                while (bytesReceived != headers.length) {
-                    bytesReceived += mInput.read(headers, bytesReceived, headers.length
-                            - bytesReceived);
-                }
-
-                ObexHelper.updateHeaderSet(request, headers);
-
-                if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
-                    mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
-                } else {
-                    mListener.setConnectionId(1);
-                }
-                // the Auth chan is initiated by the server, client sent back the authResp .
-                if (request.mAuthResp != null) {
-                    if (!handleAuthResp(request.mAuthResp)) {
-                        code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
-                        mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
-                                request.mAuthResp));
-                    }
-                    request.mAuthResp = null;
-                }
-            }
-
-            if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
-                // the Auth challenge is initiated by the client
-                // the server will send back the authResp to the client
-                if (request.mAuthChall != null) {
-                    handleAuthChall(request);
-                    reply.mAuthResp = new byte[request.mAuthResp.length];
-                    System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0,
-                            reply.mAuthResp.length);
-                    request.mAuthChall = null;
-                    request.mAuthResp = null;
-                }
-                boolean backup = false;
-                boolean create = true;
-                if (!((flags & 1) == 0)) {
-                    backup = true;
-                }
-                if (!((flags & 2) == 0)) {
-                    create = false;
-                }
-
-                try {
-                    code = mListener.onSetPath(request, reply, backup, create);
-                } catch (Exception e) {
-                    if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
-                    sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
-                    return;
-                }
-
-                code = validateResponseCode(code);
-
-                if (reply.nonce != null) {
-                    mChallengeDigest = new byte[16];
-                    System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
-                } else {
-                    mChallengeDigest = null;
-                }
-
-                long id = mListener.getConnectionId();
-                if (id == -1) {
-                    reply.mConnectionID = null;
-                } else {
-                    reply.mConnectionID = ObexHelper.convertToByteArray(id);
-                }
-
-                head = ObexHelper.createHeader(reply, false);
-                totalLength += head.length;
-
-                if (totalLength > mMaxPacketLength) {
-                    totalLength = 3;
-                    head = null;
-                    code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
-                }
-            }
-        }
-
-        // Compute Length of OBEX SETPATH packet
-        byte[] replyData = new byte[totalLength];
-        replyData[0] = (byte)code;
-        replyData[1] = (byte)(totalLength >> 8);
-        replyData[2] = (byte)totalLength;
-        if (head != null) {
-            System.arraycopy(head, 0, replyData, 3, head.length);
-        }
-        /*
-         * Write the OBEX SETPATH packet to the server. Byte 0: response code
-         * Byte 1&2: Connect Packet Length Byte 3 to n: headers
-         */
-        mOutput.write(replyData);
-        mOutput.flush();
-    }
-
-    /**
-     * Handles a disconnect request from a client. This method will read the
-     * rest of the request from the client. Assuming the request is valid, it
-     * will create a <code>HeaderSet</code> object to pass to the
-     * <code>ServerRequestHandler</code> object. After the handler processes the
-     * request, this method will create a reply message to send to the server.
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handleDisconnectRequest() throws IOException {
-        int length;
-        int code = ResponseCodes.OBEX_HTTP_OK;
-        int totalLength = 3;
-        byte[] head = null;
-        int bytesReceived;
-        HeaderSet request = new HeaderSet();
-        HeaderSet reply = new HeaderSet();
-
-        length = mInput.read();
-        length = (length << 8) + mInput.read();
-
-        if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
-            code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
-            totalLength = 3;
-        } else {
-            if (length > 3) {
-                byte[] headers = new byte[length - 3];
-                bytesReceived = mInput.read(headers);
-
-                while (bytesReceived != headers.length) {
-                    bytesReceived += mInput.read(headers, bytesReceived, headers.length
-                            - bytesReceived);
-                }
-
-                ObexHelper.updateHeaderSet(request, headers);
-            }
-
-            if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
-                mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
-            } else {
-                mListener.setConnectionId(1);
-            }
-
-            if (request.mAuthResp != null) {
-                if (!handleAuthResp(request.mAuthResp)) {
-                    code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
-                    mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
-                            request.mAuthResp));
-                }
-                request.mAuthResp = null;
-            }
-
-            if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
-
-                if (request.mAuthChall != null) {
-                    handleAuthChall(request);
-                    request.mAuthChall = null;
-                }
-
-                try {
-                    mListener.onDisconnect(request, reply);
-                } catch (Exception e) {
-                    if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
-                    sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
-                    return;
-                }
-
-                long id = mListener.getConnectionId();
-                if (id == -1) {
-                    reply.mConnectionID = null;
-                } else {
-                    reply.mConnectionID = ObexHelper.convertToByteArray(id);
-                }
-
-                head = ObexHelper.createHeader(reply, false);
-                totalLength += head.length;
-
-                if (totalLength > mMaxPacketLength) {
-                    totalLength = 3;
-                    head = null;
-                    code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
-                }
-            }
-        }
-
-        // Compute Length of OBEX CONNECT packet
-        byte[] replyData;
-        if (head != null) {
-            replyData = new byte[3 + head.length];
-        } else {
-            replyData = new byte[3];
-        }
-        replyData[0] = (byte)code;
-        replyData[1] = (byte)(totalLength >> 8);
-        replyData[2] = (byte)totalLength;
-        if (head != null) {
-            System.arraycopy(head, 0, replyData, 3, head.length);
-        }
-        /*
-         * Write the OBEX DISCONNECT packet to the server. Byte 0: response code
-         * Byte 1&2: Connect Packet Length Byte 3 to n: headers
-         */
-        mOutput.write(replyData);
-        mOutput.flush();
-    }
-
-    /**
-     * Handles a connect request from a client. This method will read the rest
-     * of the request from the client. Assuming the request is valid, it will
-     * create a <code>HeaderSet</code> object to pass to the
-     * <code>ServerRequestHandler</code> object. After the handler processes the
-     * request, this method will create a reply message to send to the server
-     * with the response code provided.
-     * @throws IOException if an error occurred at the transport layer
-     */
-    private void handleConnectRequest() throws IOException {
-        int packetLength;
-        @SuppressWarnings("unused")
-        int version;
-        @SuppressWarnings("unused")
-        int flags;
-        int totalLength = 7;
-        byte[] head = null;
-        int code = -1;
-        HeaderSet request = new HeaderSet();
-        HeaderSet reply = new HeaderSet();
-        int bytesReceived;
-
-        if(V) Log.v(TAG,"handleConnectRequest()");
-
-        /*
-         * Read in the length of the OBEX packet, OBEX version, flags, and max
-         * packet length
-         */
-        packetLength = mInput.read();
-        packetLength = (packetLength << 8) + mInput.read();
-        if(V) Log.v(TAG,"handleConnectRequest() - packetLength: " + packetLength);
-
-        version = mInput.read();
-        flags = mInput.read();
-        mMaxPacketLength = mInput.read();
-        mMaxPacketLength = (mMaxPacketLength << 8) + mInput.read();
-
-        if(V) Log.v(TAG,"handleConnectRequest() - version: " + version
-                + " MaxLength: " + mMaxPacketLength + " flags: " + flags);
-
-        // should we check it?
-        if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) {
-            mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT;
-        }
-
-        if(mMaxPacketLength > ObexHelper.getMaxTxPacketSize(mTransport)) {
-            Log.w(TAG, "Requested MaxObexPacketSize " + mMaxPacketLength
-                    + " is larger than the max size supported by the transport: "
-                    + ObexHelper.getMaxTxPacketSize(mTransport)
-                    + " Reducing to this size.");
-            mMaxPacketLength = ObexHelper.getMaxTxPacketSize(mTransport);
-        }
-
-        if (packetLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
-            code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
-            totalLength = 7;
-        } else {
-            if (packetLength > 7) {
-                byte[] headers = new byte[packetLength - 7];
-                bytesReceived = mInput.read(headers);
-
-                while (bytesReceived != headers.length) {
-                    bytesReceived += mInput.read(headers, bytesReceived, headers.length
-                            - bytesReceived);
-                }
-
-                ObexHelper.updateHeaderSet(request, headers);
-            }
-
-            if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
-                mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
-            } else {
-                mListener.setConnectionId(1);
-            }
-
-            if (request.mAuthResp != null) {
-                if (!handleAuthResp(request.mAuthResp)) {
-                    code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
-                    mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
-                            request.mAuthResp));
-                }
-                request.mAuthResp = null;
-            }
-
-            if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
-                if (request.mAuthChall != null) {
-                    handleAuthChall(request);
-                    reply.mAuthResp = new byte[request.mAuthResp.length];
-                    System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0,
-                            reply.mAuthResp.length);
-                    request.mAuthChall = null;
-                    request.mAuthResp = null;
-                }
-
-                try {
-                    code = mListener.onConnect(request, reply);
-                    code = validateResponseCode(code);
-
-                    if (reply.nonce != null) {
-                        mChallengeDigest = new byte[16];
-                        System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
-                    } else {
-                        mChallengeDigest = null;
-                    }
-                    long id = mListener.getConnectionId();
-                    if (id == -1) {
-                        reply.mConnectionID = null;
-                    } else {
-                        reply.mConnectionID = ObexHelper.convertToByteArray(id);
-                    }
-
-                    head = ObexHelper.createHeader(reply, false);
-                    totalLength += head.length;
-
-                    if (totalLength > mMaxPacketLength) {
-                        totalLength = 7;
-                        head = null;
-                        code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
-                    }
-                } catch (Exception e) {
-                    if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
-                    totalLength = 7;
-                    head = null;
-                    code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
-                }
-
-            }
-        }
-
-        // Compute Length of OBEX CONNECT packet
-        byte[] length = ObexHelper.convertToByteArray(totalLength);
-
-        /*
-         * Write the OBEX CONNECT packet to the server. Byte 0: response code
-         * Byte 1&2: Connect Packet Length Byte 3: OBEX Version Number
-         * (Presently, 0x10) Byte 4: Flags (For TCP 0x00) Byte 5&6: Max OBEX
-         * Packet Length (Defined in MAX_PACKET_SIZE) Byte 7 to n: headers
-         */
-        byte[] sendData = new byte[totalLength];
-        int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport);
-        if (maxRxLength > mMaxPacketLength) {
-            if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength +
-                    " and MaxNegotiated from Client: " + mMaxPacketLength);
-            maxRxLength = mMaxPacketLength;
-        }
-        sendData[0] = (byte)code;
-        sendData[1] = length[2];
-        sendData[2] = length[3];
-        sendData[3] = (byte)0x10;
-        sendData[4] = (byte)0x00;
-        sendData[5] = (byte)(maxRxLength >> 8);
-        sendData[6] = (byte)(maxRxLength & 0xFF);
-
-        if (head != null) {
-            System.arraycopy(head, 0, sendData, 7, head.length);
-        }
-
-        mOutput.write(sendData);
-        mOutput.flush();
-    }
-
-    /**
-     * Closes the server session - in detail close I/O streams and the
-     * underlying transport layer. Internal flag is also set so that later
-     * attempt to read/write will throw an exception.
-     */
-    public synchronized void close() {
-        if (mListener != null) {
-            mListener.onClose();
-        }
-        try {
-            /* Set state to closed before interrupting the thread by closing the streams */
-            mClosed = true;
-            if(mInput != null)
-                mInput.close();
-            if(mOutput != null)
-                mOutput.close();
-            if(mTransport != null)
-                mTransport.close();
-        } catch (Exception e) {
-            if(V) Log.d(TAG,"Exception occured during close() - ignore",e);
-        }
-        mTransport = null;
-        mInput = null;
-        mOutput = null;
-        mListener = null;
-    }
-
-    /**
-     * Verifies that the response code is valid. If it is not valid, it will
-     * return the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code.
-     * @param code the response code to check
-     * @return the valid response code or <code>OBEX_HTTP_INTERNAL_ERROR</code>
-     *         if <code>code</code> is not valid
-     */
-    private int validateResponseCode(int code) {
-
-        if ((code >= ResponseCodes.OBEX_HTTP_OK) && (code <= ResponseCodes.OBEX_HTTP_PARTIAL)) {
-            return code;
-        }
-        if ((code >= ResponseCodes.OBEX_HTTP_MULT_CHOICE)
-                && (code <= ResponseCodes.OBEX_HTTP_USE_PROXY)) {
-            return code;
-        }
-        if ((code >= ResponseCodes.OBEX_HTTP_BAD_REQUEST)
-                && (code <= ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE)) {
-            return code;
-        }
-        if ((code >= ResponseCodes.OBEX_HTTP_INTERNAL_ERROR)
-                && (code <= ResponseCodes.OBEX_HTTP_VERSION)) {
-            return code;
-        }
-        if ((code >= ResponseCodes.OBEX_DATABASE_FULL)
-                && (code <= ResponseCodes.OBEX_DATABASE_LOCKED)) {
-            return code;
-        }
-        return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
-    }
-
-    public ObexTransport getTransport() {
-        return mTransport;
-    }
-}
diff --git a/obex/javax/obex/SessionNotifier.java b/obex/javax/obex/SessionNotifier.java
deleted file mode 100644
index 9836dd6..0000000
--- a/obex/javax/obex/SessionNotifier.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Motorola, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * - Neither the name of the Motorola, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package javax.obex;
-
-import java.io.IOException;
-
-/**
- * The <code>SessionNotifier</code> interface defines a connection notifier for
- * server-side OBEX connections. When a <code>SessionNotifier</code> is created
- * and calls <code>acceptAndOpen()</code>, it will begin listening for clients
- * to create a connection at the transport layer. When the transport layer
- * connection is received, the <code>acceptAndOpen()</code> method will return a
- * <code>javax.microedition.io.Connection</code> that is the connection to the
- * client. The <code>acceptAndOpen()</code> method also takes a
- * <code>ServerRequestHandler</code> argument that will process the requests
- * from the client that connects to the server.
- * @hide
- */
-public interface SessionNotifier {
-
-    /**
-     * Waits for a transport layer connection to be established and specifies
-     * the handler to handle the requests from the client. No authenticator is
-     * associated with this connection, therefore, it is implementation
-     * dependent as to how an authentication challenge and authentication
-     * response header will be received and processed.
-     * <P>
-     * <H4>Additional Note for OBEX over Bluetooth</H4> If this method is called
-     * on a <code>SessionNotifier</code> object that does not have a
-     * <code>ServiceRecord</code> in the SDDB, the <code>ServiceRecord</code>
-     * for this object will be added to the SDDB. This method requests the BCC
-     * to put the local device in connectable mode so that it will respond to
-     * connection attempts by clients.
-     * <P>
-     * The following checks are done to verify that the service record provided
-     * is valid. If any of these checks fail, then a
-     * <code>ServiceRegistrationException</code> is thrown.
-     * <UL>
-     * <LI>ServiceClassIDList and ProtocolDescriptorList, the mandatory service
-     * attributes for a <code>btgoep</code> service record, must be present in
-     * the <code>ServiceRecord</code> associated with this notifier.
-     * <LI>L2CAP, RFCOMM and OBEX must all be in the ProtocolDescriptorList
-     * <LI>The <code>ServiceRecord</code> associated with this notifier must not
-     * have changed the RFCOMM server channel number
-     * </UL>
-     * <P>
-     * This method will not ensure that <code>ServiceRecord</code> associated
-     * with this notifier is a completely valid service record. It is the
-     * responsibility of the application to ensure that the service record
-     * follows all of the applicable syntactic and semantic rules for service
-     * record correctness.
-     * @param handler the request handler that will respond to OBEX requests
-     * @return the connection to the client
-     * @throws IOException if an error occurs in the transport layer
-     * @throws NullPointerException if <code>handler</code> is <code>null</code>
-     */
-    ObexSession acceptAndOpen(ServerRequestHandler handler) throws IOException;
-
-    /**
-     * Waits for a transport layer connection to be established and specifies
-     * the handler to handle the requests from the client and the
-     * <code>Authenticator</code> to use to respond to authentication challenge
-     * and authentication response headers.
-     * <P>
-     * <H4>Additional Note for OBEX over Bluetooth</H4> If this method is called
-     * on a <code>SessionNotifier</code> object that does not have a
-     * <code>ServiceRecord</code> in the SDDB, the <code>ServiceRecord</code>
-     * for this object will be added to the SDDB. This method requests the BCC
-     * to put the local device in connectable mode so that it will respond to
-     * connection attempts by clients.
-     * <P>
-     * The following checks are done to verify that the service record provided
-     * is valid. If any of these checks fail, then a
-     * <code>ServiceRegistrationException</code> is thrown.
-     * <UL>
-     * <LI>ServiceClassIDList and ProtocolDescriptorList, the mandatory service
-     * attributes for a <code>btgoep</code> service record, must be present in
-     * the <code>ServiceRecord</code> associated with this notifier.
-     * <LI>L2CAP, RFCOMM and OBEX must all be in the ProtocolDescriptorList
-     * <LI>The <code>ServiceRecord</code> associated with this notifier must not
-     * have changed the RFCOMM server channel number
-     * </UL>
-     * <P>
-     * This method will not ensure that <code>ServiceRecord</code> associated
-     * with this notifier is a completely valid service record. It is the
-     * responsibility of the application to ensure that the service record
-     * follows all of the applicable syntactic and semantic rules for service
-     * record correctness.
-     * @param handler the request handler that will respond to OBEX requests
-     * @param auth the <code>Authenticator</code> to use with this connection;
-     *        if <code>null</code> then no <code>Authenticator</code> will be
-     *        used
-     * @return the connection to the client
-     * @throws IOException if an error occurs in the transport layer
-     * @throws NullPointerException if <code>handler</code> is <code>null</code>
-     */
-    ObexSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth) throws IOException;
-}
