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

Commit 03f25a20 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Bluetooth OPP: Allow sending all mime-types for handover.

This change allows sending of all mime-types through
ACTION_HANDOVER_SEND and ACTION_HANDOVER_SEND_MULTIPLE.
These intent actions are only used by NFC when doing
handover transfers, and require the whitelisting
permission that is only granted to system applications.

Similarly, for receiving, we will still reject certain
mimetypes, except if the transfer was whitelisted because
it was a handover transfer.

At this moment, only the NFC service has the signature
permission required for whitelisting.

This change also allows to send files without extension,
as long as OPP has a valid mimeType. This is useful when
using OPP in combination with a content provider, which
may specify filenames without any extension but with a
valid mime-type.

Bug: 6561169
Change-Id: Ia39418de6bcb2f8af678c7b8637b63b1697eb493
parent acc04ecb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -67,6 +67,16 @@
                <action android:name="android.btopp.intent.action.WHITELIST_DEVICE" />
                <action android:name="android.btopp.intent.action.STOP_HANDOVER_TRANSFER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.btopp.intent.action.HANDOVER_SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.btopp.intent.action.HANDOVER_SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </receiver>
        <activity android:name=".opp.BluetoothOppLauncherActivity"
            android:process="@string/process"
+38 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import java.util.ArrayList;

public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
    public static final String TAG ="BluetoothOppHandoverReceiver";
    private static final boolean D = Constants.DEBUG;
@@ -31,7 +33,42 @@ public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Constants.ACTION_WHITELIST_DEVICE)) {

        if (action.equals(Constants.ACTION_HANDOVER_SEND) ||
               action.equals(Constants.ACTION_HANDOVER_SEND_MULTIPLE)) {

            BluetoothDevice device =
                    (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device == null) {
                if (D) Log.d(TAG, "No device attached to handover intent.");
                return;
            }
            if (action.equals(Constants.ACTION_HANDOVER_SEND)) {
                String type = intent.getType();
                Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
                if (stream != null && type != null) {
                    // Save type/stream, will be used when adding transfer
                    // session to DB.
                    BluetoothOppManager.getInstance(context).saveSendingFileInfo(type,
                            stream.toString(), true);
                } else {
                    if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
                }
            } else if (action.equals(Constants.ACTION_HANDOVER_SEND_MULTIPLE)) {
                ArrayList<Uri> uris = new ArrayList<Uri>();
                String mimeType = intent.getType();
                uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
                if (mimeType != null && uris != null) {
                    BluetoothOppManager.getInstance(context).saveSendingFileInfo(mimeType,
                            uris, true);
                } else {
                    if (D) Log.d(TAG, "No mimeType or stream attached to handover request");
                    return;
                }
            }
            // we already know where to send to
            BluetoothOppManager.getInstance(context).startTransfer(device);
        } else if (action.equals(Constants.ACTION_WHITELIST_DEVICE)) {
            BluetoothDevice device =
                    (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (D) Log.d(TAG, "Adding " + device + " to whitelist");
+4 −13
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ public class BluetoothOppLauncherActivity extends Activity {

        Intent intent = getIntent();
        String action = intent.getAction();
        BluetoothDevice device = null;
        boolean isHandover = false;

        if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
            /*
@@ -76,10 +74,6 @@ public class BluetoothOppLauncherActivity extends Activity {
             * probably Pictures, videos, or vCards. The Intent should contain
             * an EXTRA_STREAM with the data to attach.
             */
            if (intent.getBooleanExtra(Constants.EXTRA_CONNECTION_HANDOVER, false)) {
                device = (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                isHandover = true;
            }
            if (action.equals(Intent.ACTION_SEND)) {
                // TODO: handle type == null case
                String type = intent.getType();
@@ -96,7 +90,7 @@ public class BluetoothOppLauncherActivity extends Activity {
                    // Save type/stream, will be used when adding transfer
                    // session to DB.
                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
                            stream.toString(), isHandover);
                            stream.toString(), false);
                } else if (extra_text != null && type != null) {
                    if (V) Log.v(TAG, "Get ACTION_SEND intent with Extra_text = "
                                + extra_text.toString() + "; mimetype = " + type);
@@ -104,7 +98,7 @@ public class BluetoothOppLauncherActivity extends Activity {

                    if (fileUri != null) {
                        BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
                                fileUri.toString(), isHandover);
                                fileUri.toString(), false);
                    }
                } else {
                    Log.e(TAG, "type is null; or sending file URI is null");
@@ -119,7 +113,7 @@ public class BluetoothOppLauncherActivity extends Activity {
                    if (V) Log.v(TAG, "Get ACTION_SHARE_MULTIPLE intent: uris " + uris + "\n Type= "
                                + mimeType);
                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(mimeType,
                            uris, isHandover);
                            uris, false);
                } else {
                    Log.e(TAG, "type is null; or sending files URIs are null");
                    finish();
@@ -146,7 +140,7 @@ public class BluetoothOppLauncherActivity extends Activity {
                Intent in = new Intent(this, BluetoothOppBtEnableActivity.class);
                in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                this.startActivity(in);
            } else if (device == null) {
            } else {
                if (V) Log.v(TAG, "BT already enabled!! ");
                Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
                in1.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
@@ -159,9 +153,6 @@ public class BluetoothOppLauncherActivity extends Activity {
                        BluetoothOppReceiver.class.getName());

                this.startActivity(in1);
            } else {
                // we already know where to send to
                BluetoothOppManager.getInstance(this).startTransfer(device);
            }
        } else if (action.equals(Constants.ACTION_OPEN)) {
            Uri uri = getIntent().getData();
+16 −11
Original line number Diff line number Diff line
@@ -180,8 +180,18 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
            return ResponseCodes.OBEX_HTTP_FORBIDDEN;
        }

        String destination;
        if (mTransport instanceof BluetoothOppRfcommTransport) {
            destination = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress();
        } else {
            destination = "FF:FF:FF:00:00:00";
        }
        boolean isWhitelisted = BluetoothOppManager.getInstance(mContext).
                isWhitelisted(destination);

        try {
            boolean pre_reject = false;

            request = op.getReceivedHeader();
            if (V) Constants.logHeader(request);
            name = (String)request.getHeader(HeaderSet.NAME);
@@ -204,8 +214,9 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
                /* first we look for Mimetype in Android map */
                String extension, type;
                int dotIndex = name.lastIndexOf(".");
                if (dotIndex < 0) {
                    if (D) Log.w(TAG, "There is no file extension, reject the transfer");
                if (dotIndex < 0 && mimeType == null) {
                    if (D) Log.w(TAG, "There is no file extension or mime type," +
                            "reject the transfer");
                    pre_reject = true;
                    obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST;
                } else {
@@ -233,8 +244,8 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
            // MIME Types. Also reject everything in the "black list".
            if (!pre_reject
                    && (mimeType == null
                            || !Constants.mimeTypeMatches(mimeType,
                                    Constants.ACCEPTABLE_SHARE_INBOUND_TYPES)
                            || (!isWhitelisted && !Constants.mimeTypeMatches(mimeType,
                                    Constants.ACCEPTABLE_SHARE_INBOUND_TYPES))
                            || Constants.mimeTypeMatches(mimeType,
                                    Constants.UNACCEPTABLE_SHARE_INBOUND_TYPES))) {
                if (D) Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer");
@@ -258,12 +269,6 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
        values.put(BluetoothShare.TOTAL_BYTES, length.intValue());
        values.put(BluetoothShare.MIMETYPE, mimeType);

        String destination;
        if (mTransport instanceof BluetoothOppRfcommTransport) {
            destination = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress();
        } else {
            destination = "FF:FF:FF:00:00:00";
        }
        values.put(BluetoothShare.DESTINATION, destination);

        values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND);
@@ -277,7 +282,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen
            needConfirm = false;
        }

        if (BluetoothOppManager.getInstance(mContext).isWhitelisted(destination)) {
        if (isWhitelisted) {
            values.put(BluetoothShare.USER_CONFIRMATION,
                    BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
            needConfirm = false;
+8 −3
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ public class BluetoothOppReceiveFileInfo {

        ContentResolver contentResolver = context.getContentResolver();
        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + id);
        String filename = null, hint = null;
        String filename = null, hint = null, mimeType = null;
        long length = 0;
        Cursor metadataCursor = contentResolver.query(contentUri, new String[] {
                BluetoothShare.FILENAME_HINT, BluetoothShare.TOTAL_BYTES, BluetoothShare.MIMETYPE
@@ -101,6 +101,7 @@ public class BluetoothOppReceiveFileInfo {
                if (metadataCursor.moveToFirst()) {
                    hint = metadataCursor.getString(0);
                    length = metadataCursor.getInt(1);
                    mimeType = metadataCursor.getString(2);
                }
            } finally {
                metadataCursor.close();
@@ -142,8 +143,12 @@ public class BluetoothOppReceiveFileInfo {
        String extension = null;
        int dotIndex = filename.lastIndexOf(".");
        if (dotIndex < 0) {
            if (mimeType == null) {
                // should not happen. It must be pre-rejected
                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
            } else {
                extension = "";
            }
        } else {
            extension = filename.substring(dotIndex);
            filename = filename.substring(0, dotIndex);
Loading