109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/* 209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc. 309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * All rights reserved. 509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Redistribution and use in source and binary forms, with or without 709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * modification, are permitted provided that the following conditions are met: 809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions of source code must retain the above copyright notice, 1009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer. 1109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice, 1309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer in the documentation 1409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * and/or other materials provided with the distribution. 1509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors 1709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * may be used to endorse or promote products derived from this software 1809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * without specific prior written permission. 1909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * POSSIBILITY OF SUCH DAMAGE. 3109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 3209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypackage com.android.bluetooth.opp; 3409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentResolver; 3609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context; 37fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenenimport android.content.res.AssetFileDescriptor; 3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.Cursor; 39a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hambyimport android.database.sqlite.SQLiteException; 4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri; 4109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.provider.OpenableColumns; 42ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hambyimport android.util.Log; 43ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby 44ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hambyimport java.io.File; 45ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hambyimport java.io.FileInputStream; 46ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hambyimport java.io.FileNotFoundException; 47ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hambyimport java.io.IOException; 4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 506769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * This class stores information about a single sending file It will only be 516769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * used for outbound share. 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppSendFileInfo { 546ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue private static final String TAG = "BluetoothOppSendFileInfo"; 556ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue 566ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue private static final boolean D = Constants.DEBUG; 576ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue 586ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue private static final boolean V = Constants.VERBOSE; 596ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue 60ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby /** Reusable SendFileInfo for error status. */ 61ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby static final BluetoothOppSendFileInfo SEND_FILE_INFO_ERROR = new BluetoothOppSendFileInfo( 62ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby null, null, 0, null, BluetoothShare.STATUS_FILE_ERROR); 63ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** readable media file name */ 65fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final String mFileName; 6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** media file input stream */ 68fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final FileInputStream mInputStream; 6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** vCard string data */ 71fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final String mData; 7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 73fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final int mStatus; 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 75fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final String mMimetype; 7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 77fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly public final long mLength; 78fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly 7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** for media file */ 8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public BluetoothOppSendFileInfo(String fileName, String type, long length, 81ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby FileInputStream inputStream, int status) { 8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mFileName = fileName; 8309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mMimetype = type; 8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mLength = length; 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInputStream = inputStream; 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mStatus = status; 87fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly mData = null; 8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** for vCard, or later for vCal, vNote. Not used currently */ 91ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby public BluetoothOppSendFileInfo(String data, String type, long length, int status) { 92fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly mFileName = null; 93fa5d402906010cd17c8ed7de0dbcbfdcb78dab20Nick Pelly mInputStream = null; 9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mData = data; 9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mMimetype = type; 9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mLength = length; 9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mStatus = status; 9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 9909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 100ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby public static BluetoothOppSendFileInfo generateFileInfo(Context context, Uri uri, 101ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby String type) { 10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentResolver contentResolver = context.getContentResolver(); 103ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby String scheme = uri.getScheme(); 10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String fileName = null; 105ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby String contentType; 10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly long length = 0; 107151f41949621e082e127fe468bedd28289bc3a19Lixin Yue // Support all Uri with "content" scheme 108151f41949621e082e127fe468bedd28289bc3a19Lixin Yue // This will allow more 3rd party applications to share files via 109151f41949621e082e127fe468bedd28289bc3a19Lixin Yue // bluetooth 110ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby if ("content".equals(scheme)) { 111ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby contentType = contentResolver.getType(uri); 112a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby Cursor metadataCursor; 113a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby try { 114a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby metadataCursor = contentResolver.query(uri, new String[] { 115a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE 116a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby }, null, null, null); 117a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby } catch (SQLiteException e) { 118a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby // some content providers don't support the DISPLAY_NAME or SIZE columns 119a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby metadataCursor = null; 120a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby } 1211ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (metadataCursor != null) { 1221ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 1231ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (metadataCursor.moveToFirst()) { 1241ac5507790a87810061a19dadec36eb328a222eaTao Liejun fileName = metadataCursor.getString(0); 1253aecf54308d60eea10fe10a5c18e4dff455aef66Pradeep Panigrahi length = metadataCursor.getLong(1); 126151f41949621e082e127fe468bedd28289bc3a19Lixin Yue if (D) Log.d(TAG, "fileName = " + fileName + " length = " + length); 1271ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 1281ac5507790a87810061a19dadec36eb328a222eaTao Liejun } finally { 1291ac5507790a87810061a19dadec36eb328a222eaTao Liejun metadataCursor.close(); 13009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 132a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby if (fileName == null) { 133a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby // use last segment of URI if DISPLAY_NAME query fails 134a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby fileName = uri.getLastPathSegment(); 135a595fcc57e7f0be9cf57913cd665dc99e4001b16Jake Hamby } 136ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby } else if ("file".equals(scheme)) { 137ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby fileName = uri.getLastPathSegment(); 1381ac5507790a87810061a19dadec36eb328a222eaTao Liejun contentType = type; 139ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby File f = new File(uri.getPath()); 1401ac5507790a87810061a19dadec36eb328a222eaTao Liejun length = f.length(); 1411ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 1421ac5507790a87810061a19dadec36eb328a222eaTao Liejun // currently don't accept other scheme 143ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby return SEND_FILE_INFO_ERROR; 14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 145fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen FileInputStream is = null; 146fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen if (scheme.equals("content")) { 147fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen try { 148fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // We've found that content providers don't always have the 149fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // right size in _OpenableColumns.SIZE 150fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // As a second source of getting the correct file length, 151fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // get a file descriptor and get the stat length 152ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby AssetFileDescriptor fd = contentResolver.openAssetFileDescriptor(uri, "r"); 153fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen long statLength = fd.getLength(); 154fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen if (length != statLength && statLength > 0) { 155fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen Log.e(TAG, "Content provider length is wrong (" + Long.toString(length) + 156fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen "), using stat length (" + Long.toString(statLength) + ")"); 157fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen length = statLength; 158fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 159fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen try { 160fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // This creates an auto-closing input-stream, so 161fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // the file descriptor will be closed whenever the InputStream 162fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // is closed. 163ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby is = fd.createInputStream(); 164fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } catch (IOException e) { 165fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen try { 166fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen fd.close(); 167fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } catch (IOException e2) { 168fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // Ignore 169fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 170fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 171fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } catch (FileNotFoundException e) { 172fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen // Ignore 173fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 174fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 175fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen if (is == null) { 176fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen try { 177ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby is = (FileInputStream) contentResolver.openInputStream(uri); 178fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } catch (FileNotFoundException e) { 179ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby return SEND_FILE_INFO_ERROR; 180fdc7bd89b00e40b459c706784fa003509a229096Martijn Coenen } 18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 182151f41949621e082e127fe468bedd28289bc3a19Lixin Yue // If we can not get file length from content provider, we can try to 183151f41949621e082e127fe468bedd28289bc3a19Lixin Yue // get the length via the opened stream. 184151f41949621e082e127fe468bedd28289bc3a19Lixin Yue if (length == 0) { 1856ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue try { 1866ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue length = is.available(); 187151f41949621e082e127fe468bedd28289bc3a19Lixin Yue if (V) Log.v(TAG, "file length is " + length); 1886ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue } catch (IOException e) { 189151f41949621e082e127fe468bedd28289bc3a19Lixin Yue Log.e(TAG, "Read stream exception: ", e); 190ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby return SEND_FILE_INFO_ERROR; 1916ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue } 1926ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue } 1936ef730f85e90a8246d06c7a58bb21eee5074945cLixin Yue 194ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby return new BluetoothOppSendFileInfo(fileName, contentType, length, is, 0); 19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 197