Andorid 12蓝牙接收文件保存到bluetooth目录

安卓12 蓝牙接收文件默认保存到downloads目录
修改为bluetooth
主要修改BluetoothOppObexServerSession.java
BluetoothOppReceiveFileInfo.java

 .../opp/BluetoothOppObexServerSession.java    |  37 ++--
 .../opp/BluetoothOppReceiveFileInfo.java      | 165 ++++++++++++++----
 2 files changed, 149 insertions(+), 53 deletions(-)
 mode change 100644 => 100755 vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
 mode change 100644 => 100755 vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java

diff --git a/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java b/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
old mode 100644
new mode 100755
index 6a8013dd59..a74789cc7f
--- a/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
+++ b/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java
@@ -48,10 +48,10 @@ import com.android.bluetooth.BluetoothMetricsProto;
 import com.android.bluetooth.BluetoothObexTransport;
 import com.android.bluetooth.btservice.MetricsLogger;
 
-import java.io.FileNotFoundException;
+import java.io.BufferedOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.Arrays;
 
 import javax.obex.HeaderSet;
@@ -109,7 +109,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
     private String destination;
 
     public BluetoothOppObexServerSession(Context context, ObexTransport transport,
-            BluetoothOppService service) {
+                                         BluetoothOppService service) {
         mContext = context;
         mTransport = transport;
         mBluetoothOppService = service;
@@ -368,16 +368,14 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
 
             }
 
-            if (mFileInfo.mFileName != null && mFileInfo.mInsertUri != null) {
+            if (mFileInfo.mFileName != null) {
 
                 ContentValues updateValues = new ContentValues();
                 contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
                 updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName);
                 updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING);
-                updateValues.put(BluetoothShare.URI, mFileInfo.mInsertUri.toString());
                 mContext.getContentResolver().update(contentUri, updateValues, null, null);
 
-                mInfo.mUri = mFileInfo.mInsertUri;
                 status = receiveFile(mFileInfo, op);
                 /*
                  * TODO map status to obex response code
@@ -414,8 +412,13 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
              */
 
             Log.i(TAG, "Rejected incoming request");
-            if (mFileInfo.mInsertUri != null) {
-                mContext.getContentResolver().delete(mFileInfo.mInsertUri, null, null);
+            if (mFileInfo.mFileName != null) {
+                try {
+                    mFileInfo.mOutputStream.close();
+                } catch (IOException e) {
+                    Log.e(TAG, "error close file stream");
+                }
+                new File(mFileInfo.mFileName).delete();
             }
             // set status as local cancel
             status = BluetoothShare.STATUS_CANCELED;
@@ -437,7 +440,8 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
          */
         long beginTime = 0;
         int status = -1;
-        OutputStream os = null;
+        BufferedOutputStream bos = null;
+
         InputStream is = null;
         boolean error = false;
         try {
@@ -461,12 +465,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
         long prevPercent = 0;
 
         if (!error) {
-            try {
-                os = mContext.getContentResolver().openOutputStream(fileInfo.mInsertUri);
-            } catch (FileNotFoundException e) {
-                Log.e(TAG, "Error when openOutputStream");
-                error = true;
-            }
+            bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000);
         }
 
         if (!error) {
@@ -493,7 +492,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
                         break;
                     }
 
-                    os.write(b, 0, readLength);
+                    bos.write(b, 0, readLength);
                     position += readLength;
                     percent = position * 100 / fileInfo.mLength;
                     currentTime = SystemClock.elapsedRealtime();
@@ -555,10 +554,9 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
             }
         }
 
-        if (os != null) {
+        if (bos != null) {
             try {
-                os.flush();
-                os.close();
+                bos.close();
             } catch (IOException e) {
                 Log.e(TAG, "Error when closing stream after send");
             }
@@ -669,3 +667,4 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
         }
     }
 }
+
diff --git a/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java b/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
old mode 100644
new mode 100755
index 1589988db4..c53fceeb9b
--- a/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
+++ b/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java
@@ -38,13 +38,15 @@ import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
-import android.provider.MediaStore;
+import android.os.StatFs;
+import android.os.SystemClock;
 import android.util.Log;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
+import java.util.Random;
 
 /**
  * This class stores information about a single receiving file. It will only be
@@ -56,8 +58,8 @@ public class BluetoothOppReceiveFileInfo {
     private static final boolean V = Constants.VERBOSE;
     private static String sDesiredStoragePath = null;
 
-    /* To truncate the name of the received file if the length exceeds 237 */
-    private static final int OPP_LENGTH_OF_FILE_NAME = 237;
+    /* To truncate the name of the received file if the length exceeds 245 */
+    private static final int OPP_LENGTH_OF_FILE_NAME = 244;
 
 
     /** absolute store file name */
@@ -65,22 +67,23 @@ public class BluetoothOppReceiveFileInfo {
 
     public long mLength;
 
+    public FileOutputStream mOutputStream;
+
     public int mStatus;
 
     public String mData;
 
-    public Uri mInsertUri;
-
     public BluetoothOppReceiveFileInfo(String data, long length, int status) {
         mData = data;
         mStatus = status;
         mLength = length;
     }
 
-    public BluetoothOppReceiveFileInfo(String filename, long length, Uri insertUri, int status) {
+    public BluetoothOppReceiveFileInfo(String filename, long length, FileOutputStream outputStream,
+                                       int status) {
         mFileName = filename;
+        mOutputStream = outputStream;
         mStatus = status;
-        mInsertUri = insertUri;
         mLength = length;
     }
 
@@ -110,13 +113,39 @@ public class BluetoothOppReceiveFileInfo {
             }
         }
 
-        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+        File base = null;
+        StatFs stat = null;
+
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            String root = Environment.getExternalStorageDirectory().getPath();
+            base = new File(root + Constants.DEFAULT_STORE_SUBDIR);
+            if (!base.isDirectory() && !base.mkdir()) {
+                if (D) {
+                    Log.d(Constants.TAG,
+                            "Receive File aborted - can't create base directory " + base.getPath());
+                }
+                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
+            }
+            stat = new StatFs(base.getPath());
+        } else {
             if (D) {
                 Log.d(Constants.TAG, "Receive File aborted - no external storage");
             }
             return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_ERROR_NO_SDCARD);
         }
 
+        /*
+         * Check whether there's enough space on the target filesystem to save
+         * the file. Put a bit of margin (in case creating the file grows the
+         * system by a few blocks).
+         */
+        if (stat.getBlockSizeLong() * (stat.getAvailableBlocksLong() - 4) < length) {
+            if (D) {
+                Log.d(Constants.TAG, "Receive File aborted - not enough free space");
+            }
+            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_ERROR_SDCARD_FULL);
+        }
+
         filename = choosefilename(hint);
         if (filename == null) {
             // should not happen. It must be pre-rejected
@@ -140,13 +169,13 @@ public class BluetoothOppReceiveFileInfo {
         }
 
         if (filename.getBytes().length > OPP_LENGTH_OF_FILE_NAME) {
-          /* Including extn of the file, Linux supports 255 character as a maximum length of the
-           * file name to be created. Hence, Instead of sending OBEX_HTTP_INTERNAL_ERROR,
-           * as a response, truncate the length of the file name and save it. This check majorly
-           * helps in the case of vcard, where Phone book app supports contact name to be saved
-           * more than 255 characters, But the server rejects the card just because the length of
-           * vcf file name received exceeds 255 Characters.
-           */
+            /* Including extn of the file, Linux supports 255 character as a maximum length of the
+             * file name to be created. Hence, Instead of sending OBEX_HTTP_INTERNAL_ERROR,
+             * as a response, truncate the length of the file name and save it. This check majorly
+             * helps in the case of vcard, where Phone book app supports contact name to be saved
+             * more than 255 characters, But the server rejects the card just because the length of
+             * vcf file name received exceeds 255 Characters.
+             */
             Log.i(Constants.TAG, " File Name Length :" + filename.length());
             Log.i(Constants.TAG, " File Name Length in Bytes:" + filename.getBytes().length);
 
@@ -163,33 +192,100 @@ public class BluetoothOppReceiveFileInfo {
             }
         }
 
-        DateFormat dateFormat = new SimpleDateFormat("_hhmmss");
-        String currentTime = dateFormat.format(Calendar.getInstance().getTime());
-        String fullfilename = filename + currentTime + extension;
+        filename = base.getPath() + File.separator + filename;
+        // Generate a unique filename, create the file, return it.
+        String fullfilename = chooseUniquefilename(filename, extension);
 
+        if (!safeCanonicalPath(fullfilename)) {
+            // If this second check fails, then we better reject the transfer
+            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
+        }
         if (V) {
             Log.v(Constants.TAG, "Generated received filename " + fullfilename);
         }
 
-        Uri insertUri = null;
-        ContentValues mediaContentValues = new ContentValues();
-        mediaContentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fullfilename);
-        mediaContentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
-        mediaContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,
-                Environment.DIRECTORY_DOWNLOADS);
-        insertUri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI,
-                mediaContentValues);
+        if (fullfilename != null) {
+            try {
+                new FileOutputStream(fullfilename).close();
+                int index = fullfilename.lastIndexOf('/') + 1;
+                // update display name
+                if (index > 0) {
+                    String displayName = fullfilename.substring(index);
+                    if (V) {
+                        Log.v(Constants.TAG, "New display name " + displayName);
+                    }
+                    ContentValues updateValues = new ContentValues();
+                    updateValues.put(BluetoothShare.FILENAME_HINT, displayName);
+                    context.getContentResolver().update(contentUri, updateValues, null, null);
 
-        if (insertUri == null) {
-            if (D) {
-                Log.e(Constants.TAG, "Error when creating file " + fullfilename);
+                }
+                return new BluetoothOppReceiveFileInfo(fullfilename, length,
+                        new FileOutputStream(fullfilename), 0);
+            } catch (IOException e) {
+                if (D) {
+                    Log.e(Constants.TAG, "Error when creating file " + fullfilename);
+                }
+                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
             }
+        } else {
             return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
         }
 
-        Log.d(Constants.TAG, "file crated, insertUri:" + insertUri.toString());
+    }
+
+    private static boolean safeCanonicalPath(String uniqueFileName) {
+        try {
+            File receiveFile = new File(uniqueFileName);
+            if (sDesiredStoragePath == null) {
+                sDesiredStoragePath = Environment.getExternalStorageDirectory().getPath()
+                        + Constants.DEFAULT_STORE_SUBDIR;
+            }
+            String canonicalPath = receiveFile.getCanonicalPath();
+
+            // Check if canonical path is complete - case sensitive-wise
+            if (!canonicalPath.startsWith(sDesiredStoragePath)) {
+                return false;
+            }
+
+            return true;
+        } catch (IOException ioe) {
+            // If an exception is thrown, there might be something wrong with the file.
+            return false;
+        }
+    }
 
-        return new BluetoothOppReceiveFileInfo(fullfilename, length, insertUri, 0);
+    private static String chooseUniquefilename(String filename, String extension) {
+        String fullfilename = filename + extension;
+        if (!new File(fullfilename).exists()) {
+            return fullfilename;
+        }
+        filename = filename + Constants.FILENAME_SEQUENCE_SEPARATOR;
+        /*
+         * This number is used to generate partially randomized filenames to
+         * avoid collisions. It starts at 1. The next 9 iterations increment it
+         * by 1 at a time (up to 10). The next 9 iterations increment it by 1 to
+         * 10 (random) at a time. The next 9 iterations increment it by 1 to 100
+         * (random) at a time. ... Up to the point where it increases by
+         * 100000000 at a time. (the maximum value that can be reached is
+         * 1000000000) As soon as a number is reached that generates a filename
+         * that doesn't exist, that filename is used. If the filename coming in
+         * is [base].[ext], the generated filenames are [base]-[sequence].[ext].
+         */
+        Random rnd = new Random(SystemClock.uptimeMillis());
+        int sequence = 1;
+        for (int magnitude = 1; magnitude < 1000000000; magnitude *= 10) {
+            for (int iteration = 0; iteration < 9; ++iteration) {
+                fullfilename = filename + sequence + extension;
+                if (!new File(fullfilename).exists()) {
+                    return fullfilename;
+                }
+                if (V) {
+                    Log.v(Constants.TAG, "file with sequence number " + sequence + " exists");
+                }
+                sequence += rnd.nextInt(magnitude) + 1;
+            }
+        }
+        return null;
     }
 
     private static String choosefilename(String hint) {
@@ -218,3 +314,4 @@ public class BluetoothOppReceiveFileInfo {
         return filename;
     }
 }
+
-- 
2.29.0


你可能感兴趣的:(java,android,jvm)