Merge "Enhanced support to OPP content share"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b0dea34..23c6093 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -188,4 +188,7 @@
     <string name="transfer_menu_clear">Clear from list</string>
     <string name="transfer_clear_dlg_title">Clear</string>
 
+     <!-- Do not translate. file name used for sharing. -->
+    <string name="bluetooth_share_file_name" translate="false">bluetooth_content_share</string>
+
 </resources>
diff --git a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
index 413f896..353cadc 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
@@ -34,11 +34,16 @@
 
 import com.android.bluetooth.R;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.ArrayList;
+
 import android.app.Activity;
-import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothDevicePicker;
 import android.content.Intent;
+import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
@@ -71,6 +76,12 @@
                 // TODO: handle type == null case
                 String type = intent.getType();
                 Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
+                CharSequence extra_text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
+                // If we get ACTION_SEND intent with EXTRA_STREAM, we'll use the
+                // uri data;
+                // If we get ACTION_SEND intent without EXTRA_STREAM, but with
+                // EXTRA_TEXT, we will try send this TEXT out; Currently in
+                // Browser, share one link goes to this case;
                 if (stream != null && type != null) {
                     if (V) Log.v(TAG, "Get ACTION_SEND intent: Uri = " + stream + "; mimetype = "
                                 + type);
@@ -78,6 +89,15 @@
                     // session to DB.
                     BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
                             stream.toString());
+                } else if (extra_text != null && type != null) {
+                    if (V) Log.v(TAG, "Get ACTION_SEND intent with Extra_text = "
+                                + extra_text.toString() + "; mimetype = " + type);
+                    Uri fileUri = creatFileForSharedContent(this, extra_text);
+
+                    if (fileUri != null) {
+                        BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
+                                fileUri.toString());
+                    }
                 } else {
                     Log.e(TAG, "type is null; or sending file URI is null");
                     finish();
@@ -149,4 +169,48 @@
         return Settings.System.getInt(this.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
                 0) == 1;
     }
+    private Uri creatFileForSharedContent(Context context, CharSequence shareContent) {
+        if (shareContent == null) {
+            return null;
+        }
+
+        Uri fileUri = null;
+        FileOutputStream outStream = null;
+        try {
+            String fileName = getString(R.string.bluetooth_share_file_name) + ".html";
+            context.deleteFile(fileName);
+
+            String uri = shareContent.toString();
+            String content = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;"
+                + " charset=UTF-8\"/></head><body>" + "<a href=\"" + uri + "\">" + uri + "</a></p>"
+                + "</body></html>";
+            byte[] byteBuff = content.getBytes();
+
+            outStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
+            if (outStream != null) {
+                outStream.write(byteBuff, 0, byteBuff.length);
+                fileUri = Uri.fromFile(new File(context.getFilesDir(), fileName));
+                if (fileUri != null) {
+                    if (D) Log.d(TAG, "Created one file for shared content: "
+                            + fileUri.toString());
+                }
+            }
+        } catch (FileNotFoundException e) {
+            Log.e(TAG, "FileNotFoundException: " + e.toString());
+            e.printStackTrace();
+        } catch (IOException e) {
+            Log.e(TAG, "IOException: " + e.toString());
+        } catch (Exception e) {
+            Log.e(TAG, "Exception: " + e.toString());
+        } finally {
+            try {
+                if (outStream != null) {
+                    outStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return fileUri;
+    }
 }
diff --git a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
index 7450456..44ca9bd 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java
@@ -99,17 +99,16 @@
 
     public static BluetoothOppSendFileInfo generateFileInfo(Context context, String uri,
             String type, String dest) {
-        //TODO consider uri is a file:// uri
         ContentResolver contentResolver = context.getContentResolver();
         Uri u = Uri.parse(uri);
         String scheme = u.getScheme();
-        String authority = u.getAuthority();
         String fileName = null;
         String contentType = null;
         long length = 0;
-        if (scheme.equals("content") && authority.equals("media")
-                || type.equals(Contacts.CONTENT_VCARD_TYPE)) {
-
+        // Support all Uri with "content" scheme
+        // This will allow more 3rd party applications to share files via
+        // bluetooth
+        if (scheme.equals("content")) {
             contentType = contentResolver.getType(u);
             Cursor metadataCursor = contentResolver.query(u, new String[] {
                     OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
@@ -119,6 +118,7 @@
                     if (metadataCursor.moveToFirst()) {
                         fileName = metadataCursor.getString(0);
                         length = metadataCursor.getInt(1);
+                        if (D) Log.d(TAG, "fileName = " + fileName + " length = " + length);
                     }
                 } finally {
                     metadataCursor.close();
@@ -142,14 +142,14 @@
                     BluetoothShare.STATUS_FILE_ERROR, dest);
         }
 
-        // VCard stream length got from content provider is 0, we can only get
-        // the real value after the real encoding process complete
-        if (type.equals(Contacts.CONTENT_VCARD_TYPE)) {
+        // If we can not get file length from content provider, we can try to
+        // get the length via the opened stream.
+        if (length == 0) {
             try {
                 length = is.available();
-                if (V) Log.v(TAG, "Contacts file length is " + length);
+                if (V) Log.v(TAG, "file length is " + length);
             } catch (IOException e) {
-                Log.e(TAG, "Read contacts vcard stream exception: ", e);
+                Log.e(TAG, "Read stream exception: ", e);
                 return new BluetoothOppSendFileInfo(null, null, 0, null,
                         BluetoothShare.STATUS_FILE_ERROR, dest);
             }