Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c020ce0 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Opp: Use MediaStore to handle received file" am: c2d8988a am: b89761d5

Change-Id: I2cd079305c956c13a6ac03ef0bdaf585d8fac050
parents 97eb5238 b89761d5
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -82,8 +82,7 @@
        android:supportsRtl="true"
        android:usesCleartextTraffic="false"
        android:directBootAware="true"
        android:defaultToDeviceProtectedStorage="true"
        android:requestLegacyExternalStorage="true">
        android:defaultToDeviceProtectedStorage="true">
        <uses-library android:name="javax.obex" />
        <provider android:name=".opp.BluetoothOppProvider"
            android:authorities="com.android.bluetooth.opp"
+2 −3
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.util.Log;

import java.io.File;
import java.util.ArrayList;

/**
@@ -148,8 +147,8 @@ public class BluetoothOppBatch {
            BluetoothOppShareInfo info = mShares.get(i);

            if (info.mStatus < 200) {
                if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mFilename != null) {
                    new File(info.mFilename).delete();
                if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mUri != null) {
                    mContext.getContentResolver().delete(info.mUri, null, null);
                }
                if (V) {
                    Log.v(TAG, "Cancel batch for info " + info.mId);
+18 −16
Original line number Diff line number Diff line
@@ -48,10 +48,10 @@ import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.BluetoothObexTransport;
import com.android.bluetooth.btservice.MetricsLogger;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

import javax.obex.HeaderSet;
@@ -361,14 +361,16 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler

            }

            if (mFileInfo.mFileName != null) {
            if (mFileInfo.mFileName != null && mFileInfo.mInsertUri != 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
@@ -403,13 +405,8 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
             */

            Log.i(TAG, "Rejected incoming request");
            if (mFileInfo.mFileName != null) {
                try {
                    mFileInfo.mOutputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "error close file stream");
                }
                new File(mFileInfo.mFileName).delete();
            if (mFileInfo.mInsertUri != null) {
                mContext.getContentResolver().delete(mFileInfo.mInsertUri, null, null);
            }
            // set status as local cancel
            status = BluetoothShare.STATUS_CANCELED;
@@ -430,8 +427,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
         * implement receive file
         */
        int status = -1;
        BufferedOutputStream bos = null;

        OutputStream os = null;
        InputStream is = null;
        boolean error = false;
        try {
@@ -455,7 +451,12 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
        long prevPercent = 0;

        if (!error) {
            bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000);
            try {
                os = mContext.getContentResolver().openOutputStream(fileInfo.mInsertUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Error when openOutputStream");
                error = true;
            }
        }

        if (!error) {
@@ -481,7 +482,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
                        break;
                    }

                    bos.write(b, 0, readLength);
                    os.write(b, 0, readLength);
                    position += readLength;
                    percent = position * 100 / fileInfo.mLength;
                    currentTime = SystemClock.elapsedRealtime();
@@ -536,9 +537,10 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler
            }
        }

        if (bos != null) {
        if (os != null) {
            try {
                bos.close();
                os.flush();
                os.close();
            } catch (IOException e) {
                Log.e(TAG, "Error when closing stream after send");
            }
+20 −121
Original line number Diff line number Diff line
@@ -38,15 +38,10 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * This class stores information about a single receiving file. It will only be
@@ -67,23 +62,22 @@ 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, FileOutputStream outputStream,
            int status) {
    public BluetoothOppReceiveFileInfo(String filename, long length, Uri insertUri, int status) {
        mFileName = filename;
        mOutputStream = outputStream;
        mStatus = status;
        mInsertUri = insertUri;
        mLength = length;
    }

@@ -113,39 +107,13 @@ public class BluetoothOppReceiveFileInfo {
            }
        }

        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 (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            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
@@ -192,100 +160,31 @@ public class BluetoothOppReceiveFileInfo {
            }
        }

        filename = base.getPath() + File.separator + filename;
        // Generate a unique filename, create the file, return it.
        String fullfilename = chooseUniquefilename(filename, extension);
        String fullfilename = 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);
        }

        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);
        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);

                }
                return new BluetoothOppReceiveFileInfo(fullfilename, length,
                        new FileOutputStream(fullfilename), 0);
            } catch (IOException e) {
        if (insertUri == null) {
            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;
        }
    }

    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;
        return new BluetoothOppReceiveFileInfo(fullfilename, length, insertUri, 0);
    }

    private static String choosefilename(String hint) {
+4 −5
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import android.util.Log;

import com.android.bluetooth.BluetoothObexTransport;

import java.io.File;
import java.io.IOException;

import javax.obex.ObexTransport;
@@ -402,8 +401,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                failReason = mCurrentShare.mStatus;
            }
            if (mCurrentShare.mDirection == BluetoothShare.DIRECTION_INBOUND
                    && mCurrentShare.mFilename != null) {
                new File(mCurrentShare.mFilename).delete();
                    && mCurrentShare.mUri != null) {
                mContext.getContentResolver().delete(mCurrentShare.mUri, null, null);
            }
        }

@@ -429,8 +428,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                        updateValues.put(BluetoothShare.MIMETYPE, fileInfo.mMimetype);
                    }
                } else {
                    if (info.mStatus < 200 && info.mFilename != null) {
                        new File(info.mFilename).delete();
                    if (info.mStatus < 200 && info.mUri != null) {
                        mContext.getContentResolver().delete(info.mUri, null, null);
                    }
                }
                mContext.getContentResolver().update(contentUri, updateValues, null, null);
Loading