Add OBEX object count support to Bluetooth.

To support Android Beam receiving information about
the number of files in a OPP transfer, add the Count
OBEX header. Also add a new intent to tell the handover
requested that a transfer has started, including the
count (if any).

Change-Id: Ib5e0e8dbc6c2e3259e0f732a507557c3688e168c
diff --git a/src/com/android/bluetooth/opp/BluetoothOppBatch.java b/src/com/android/bluetooth/opp/BluetoothOppBatch.java
index 7f51fe2..08701c4 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppBatch.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppBatch.java
@@ -187,6 +187,10 @@
         return (mShares.size() == 0);
     }
 
+    public int getNumShares() {
+        return mShares.size();
+    }
+
     /**
      * Get the running status of the batch
      * @return
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
index dce7fa3..d3eb881 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
@@ -83,10 +83,10 @@
         mTransport = transport;
     }
 
-    public void start(Handler handler) {
+    public void start(Handler handler, int numShares) {
         if (D) Log.d(TAG, "Start!");
         mCallback = handler;
-        mThread = new ClientThread(mContext, mTransport);
+        mThread = new ClientThread(mContext, mTransport, numShares);
         mThread.start();
     }
 
@@ -140,13 +140,15 @@
 
         private boolean mConnected = false;
 
-        public ClientThread(Context context, ObexTransport transport) {
+        private int mNumShares;
+
+        public ClientThread(Context context, ObexTransport transport, int initialNumShares) {
             super("BtOpp ClientThread");
             mContext1 = context;
             mTransport1 = transport;
             waitingForShare = true;
             mWaitingForRemote = false;
-
+            mNumShares = initialNumShares;
             PowerManager pm = (PowerManager)mContext1.getSystemService(Context.POWER_SERVICE);
             wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         }
@@ -171,7 +173,7 @@
                 mInterrupted = true;
             }
             if (!mInterrupted) {
-                connect();
+                connect(mNumShares);
             }
 
             while (!mInterrupted) {
@@ -229,7 +231,7 @@
             }
         }
 
-        private void connect() {
+        private void connect(int numShares) {
             if (D) Log.d(TAG, "Create ClientSession with transport " + mTransport1.toString());
             try {
                 mCs = new ClientSession(mTransport1);
@@ -240,6 +242,7 @@
             if (mConnected) {
                 mConnected = false;
                 HeaderSet hs = new HeaderSet();
+                hs.setHeader(HeaderSet.COUNT, (long) numShares);
                 synchronized (this) {
                     mWaitingForRemote = true;
                 }
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
index 3512fad..5bd54af 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
@@ -128,7 +128,7 @@
     /**
      * Called from BluetoothOppTransfer to start the "Transfer"
      */
-    public void start(Handler handler) {
+    public void start(Handler handler, int numShares) {
         if (D) Log.d(TAG, "Start!");
         mCallback = handler;
 
@@ -286,6 +286,7 @@
             values.put(BluetoothShare.USER_CONFIRMATION,
                     BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
             needConfirm = false;
+
         }
 
         Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
@@ -539,16 +540,39 @@
 
         if (D) Log.d(TAG, "onConnect");
         if (V) Constants.logHeader(request);
+        Long objectCount = null;
         try {
             byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET);
             if (V) Log.v(TAG, "onConnect(): uuid =" + Arrays.toString(uuid));
             if(uuid != null) {
                  return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
             }
+
+            objectCount = (Long) request.getHeader(HeaderSet.COUNT);
         } catch (IOException e) {
             Log.e(TAG, e.toString());
             return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
         }
+        String destination;
+        if (mTransport instanceof BluetoothOppRfcommTransport) {
+            destination = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress();
+        } else {
+            destination = "FF:FF:FF:00:00:00";
+        }
+        boolean isHandover = BluetoothOppManager.getInstance(mContext).
+                isWhitelisted(destination);
+        if (isHandover) {
+            // Notify the handover requester file transfer has started
+            Intent intent = new Intent(Constants.ACTION_HANDOVER_STARTED);
+            if (objectCount != null) {
+                intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT, objectCount.intValue());
+            } else {
+                intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT,
+                        Constants.COUNT_HEADER_UNAVAILABLE);
+            }
+            intent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, destination);
+            mContext.sendBroadcast(intent, Constants.HANDOVER_STATUS_PERMISSION);
+        }
         mTimestamp = System.currentTimeMillis();
         return ResponseCodes.OBEX_HTTP_OK;
     }
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexSession.java
index ce16875..19c98d2 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexSession.java
@@ -66,7 +66,7 @@
 
     int SESSION_TIMEOUT = 50000;
 
-    void start(Handler sessionHandler);
+    void start(Handler sessionHandler, int numShares);
 
     void stop();
 
diff --git a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
index 2be679c..2dbed49 100755
--- a/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
@@ -453,7 +453,7 @@
             if (V) Log.v(TAG, "Transfer has Server session" + mSession.toString());
         }
 
-        mSession.start(mSessionHandler);
+        mSession.start(mSessionHandler, mBatch.getNumShares());
         processCurrentShare();
     }
 
diff --git a/src/com/android/bluetooth/opp/Constants.java b/src/com/android/bluetooth/opp/Constants.java
index 3b452b5..5a07955 100644
--- a/src/com/android/bluetooth/opp/Constants.java
+++ b/src/com/android/bluetooth/opp/Constants.java
@@ -88,6 +88,10 @@
     public static final String ACTION_HANDOVER_SEND_MULTIPLE =
             "android.btopp.intent.action.HANDOVER_SEND_MULTIPLE";
 
+    /** the intent that is used for indicating an incoming transfer*/
+    public static final String ACTION_HANDOVER_STARTED =
+            "android.btopp.intent.action.BT_OPP_HANDOVER_STARTED";
+
     /** intent action used to indicate the progress of a handover transfer */
     public static final String ACTION_BT_OPP_TRANSFER_PROGRESS =
             "android.btopp.intent.action.BT_OPP_TRANSFER_PROGRESS";
@@ -104,6 +108,10 @@
     public static final String EXTRA_BT_OPP_ADDRESS =
             "android.btopp.intent.extra.BT_OPP_ADDRESS";
 
+    public static final String EXTRA_BT_OPP_OBJECT_COUNT =
+            "android.btopp.intent.extra.BT_OPP_OBJECT_COUNT";
+
+    public static final int COUNT_HEADER_UNAVAILABLE = -1;
     public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
 
     public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;