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

Commit f5160d45 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Additional changes to support Bluetooth Beam.

- Added a whitelist permission, to ensure only system
  services (such as NFC) can whitelist MAC addresses.
- Added HANDOVER_STATUS permission, to ensure handover
  transfer status can only be received by eligible services
  (such as NFC).
- Added new confirmation type HANDOVER_CONFIRMED; this indicates
  the transfer was initiated by a handover, and doesn't need to be
  confirmed. This type is also reused to send broadcasts
  to the NFC service, so the NFC service can show notifications
  and deal with the received data.
- Added 15 second timeout to whitelist.
- Modify notication code to not show any notifications for handover
  transfers; instead, send broadcasts to indicate handover status.
- Modify "transfer complete" code to sendbroasts to indicate handover
  status.
Change-Id: I00c08e09eaf44f0bd4bd837cb6b0c37b802742bc
parent 0e2784a4
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -10,6 +10,19 @@
        android:label="@string/permlab_bluetoothShareManager"
        android:description="@string/permdesc_bluetoothShareManager"
        android:protectionLevel="signature" />

    <!--  Allows temporarily whitelisting Bluetooth addresses for sharing -->
    <permission android:name="com.android.permission.WHITELIST_BLUETOOTH_DEVICE"
        android:label="@string/permlab_bluetoothWhitelist"
        android:description="@string/permdesc_bluetoothWhitelist"
        android:protectionLevel="signature" />

    <!--  Allows receiving handover status broadcasts from Bluetooth -->,
    <permission android:name="com.android.permission.HANDOVER_STATUS"
        android:label="@string/permlab_handoverStatus"
        android:description="@string/permdesc_handoverStatus"
        android:protectionLevel="signature" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_SHARE" />
    <uses-permission android:name="android.permission.INTERNET" />
@@ -21,6 +34,7 @@
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="com.android.permission.HANDOVER_STATUS" />
    <application
        android:icon="@drawable/bt_share"
        android:label="@string/app_name">
@@ -43,7 +57,14 @@
                <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
                <!--action android:name="android.intent.action.BOOT_COMPLETED" /-->
                <action android:name="android.btopp.intent.action.OPEN_RECEIVED_FILES" />
                <action android:name="todo-whitelist" />
            </intent-filter>
        </receiver>
         <receiver
            android:process="@string/process"
            android:name=".opp.BluetoothOppHandoverReceiver"
            android:permission="com.android.permission.WHITELIST_BLUETOOTH_DEVICE">
            <intent-filter>
                <action android:name="android.btopp.intent.action.WHITELIST_DEVICE" />
            </intent-filter>
        </receiver>
        <activity android:name=".opp.BluetoothOppLauncherActivity"
+11 −0
Original line number Diff line number Diff line
@@ -32,6 +32,17 @@
    <string name="permdesc_bluetoothShareManager">Allows the app to access the
        BluetoothShare manager and use it to transfer files. </string>

    <string name="permlab_bluetoothWhitelist">Whitelist bluetooth device access.</string>

    <string name="permdesc_bluetoothWhitelist">Allows the app to temporarily whitelist
        a Bluetooth device, allowing that device to send files to this device without user
        confirmation.</string>

    <!-- Strings used for a (system only) permission -->
    <string name="permlab_handoverStatus">Receive BT handover transfer broadcasts.</string>
    <string name="permdesc_handoverStatus">Allows receiving handover transfer status
        information from Bluetooth.</string>

    <!-- string showed on "Share picutre via" dialog -->
    <string name="bt_share_picker_label">Bluetooth</string>

+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.opp;

import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
    public static final String TAG ="BluetoothOppHandoverReceiver";
    private static final boolean D = Constants.DEBUG;
    private static final boolean V = Constants.VERBOSE;

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Constants.ACTION_WHITELIST_DEVICE)) {
            BluetoothDevice device =
                    (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (D) Log.d(TAG, "Adding " + device + " to whitelist");
            if (device == null) return;
            BluetoothOppManager.getInstance(context).addToWhitelist(device.getAddress());
        } else {
            if (D) Log.d(TAG, "Unknown action: " + action);
        }
    }

}
+9 −6
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ public class BluetoothOppLauncherActivity extends Activity {
        Intent intent = getIntent();
        String action = intent.getAction();
        BluetoothDevice device = null;
        boolean isHandover = true;

        if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
            /*
@@ -75,14 +76,15 @@ 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();
                Uri stream = (Uri)intent.getParcelableExtra(Intent.EXTRA_STREAM);
                CharSequence extra_text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
                //TODO: consider only checking EXTRA_DEVICE if it came from NFC
                device = (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                // 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
@@ -94,7 +96,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());
                            stream.toString(), isHandover);
                } else if (extra_text != null && type != null) {
                    if (V) Log.v(TAG, "Get ACTION_SEND intent with Extra_text = "
                                + extra_text.toString() + "; mimetype = " + type);
@@ -102,7 +104,7 @@ public class BluetoothOppLauncherActivity extends Activity {

                    if (fileUri != null) {
                        BluetoothOppManager.getInstance(this).saveSendingFileInfo(type,
                                fileUri.toString());
                                fileUri.toString(), isHandover);
                    }
                } else {
                    Log.e(TAG, "type is null; or sending file URI is null");
@@ -116,7 +118,8 @@ public class BluetoothOppLauncherActivity extends Activity {
                if (mimeType != null && uris != null) {
                    if (V) Log.v(TAG, "Get ACTION_SHARE_MULTIPLE intent: uris " + uris + "\n Type= "
                                + mimeType);
                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(mimeType, uris);
                    BluetoothOppManager.getInstance(this).saveSendingFileInfo(mimeType,
                            uris, isHandover);
                } else {
                    Log.e(TAG, "type is null; or sending files URIs are null");
                    finish();
+51 −10
Original line number Diff line number Diff line
@@ -43,10 +43,13 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Process;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
@@ -77,6 +80,8 @@ public class BluetoothOppManager {

    private ArrayList<Uri> mUrisOfSendingFiles;

    private boolean mIsHandoverInitiated;

    private static final String OPP_PREFERENCE_FILE = "OPPMGR";

    private static final String SENDING_FLAG = "SENDINGFLAG";
@@ -105,6 +110,13 @@ public class BluetoothOppManager {

    private int mInsertShareThreadNum = 0;

    // A list of devices that may send files over OPP to this device
    // without user confirmation. Used for connection handover from forex NFC.
    private List<Pair<String,Long> > mWhitelist = new ArrayList<Pair<String, Long> >();

    // The time for which the whitelist entries remain valid.
    private static final int WHITELIST_DURATION_MS = 15000;

    /**
     * Get singleton instance.
     */
@@ -140,15 +152,31 @@ public class BluetoothOppManager {
        return true;
    }

    List<String> mWhitelist = new ArrayList<String>();

    private void cleanupWhitelist() {
        // Removes expired entries
        long curTime = SystemClock.elapsedRealtime();
        for (Iterator<Pair<String,Long>> iter = mWhitelist.iterator(); iter.hasNext(); ) {
            Pair<String,Long> entry = iter.next();
            if (curTime - entry.second > WHITELIST_DURATION_MS) {
                if (V) Log.v(TAG, "Cleaning out whitelist entry " + entry.first);
                iter.remove();
            }
        }
    }

    public void addToWhitelist(String address) {
        //TODO: timeout whitelist
        mWhitelist.add(address);
        if (address == null) return;

        mWhitelist.add(new Pair<String, Long>(address, SystemClock.elapsedRealtime()));
    }

    public boolean isWhitelisted(String address) {
        return mWhitelist.contains(address);
        cleanupWhitelist();
        for (Pair<String,Long> entry : mWhitelist) {
            if (entry.first.equals(address)) return true;
        }
        return false;
    }

    /**
@@ -212,20 +240,22 @@ public class BluetoothOppManager {
        if (V) Log.v(TAG, "Application data stored to SharedPreference! ");
    }

    public void saveSendingFileInfo(String mimeType, String uri) {
    public void saveSendingFileInfo(String mimeType, String uri, boolean isHandover) {
        synchronized (BluetoothOppManager.this) {
            mMultipleFlag = false;
            mMimeTypeOfSendingFile = mimeType;
            mUriOfSendingFile = uri;
            mIsHandoverInitiated = isHandover;
            storeApplicationData();
        }
    }

    public void saveSendingFileInfo(String mimeType, ArrayList<Uri> uris) {
    public void saveSendingFileInfo(String mimeType, ArrayList<Uri> uris, boolean isHandover) {
        synchronized (BluetoothOppManager.this) {
            mMultipleFlag = true;
            mMimeTypeOfSendingFiles = mimeType;
            mUrisOfSendingFiles = uris;
            mIsHandoverInitiated = isHandover;
            storeApplicationData();
        }
    }
@@ -306,7 +336,8 @@ public class BluetoothOppManager {
                return;
            }
            insertThread = new InsertShareInfoThread(device, mMultipleFlag, mMimeTypeOfSendingFile,
                    mUriOfSendingFile, mMimeTypeOfSendingFiles, mUrisOfSendingFiles);
                    mUriOfSendingFile, mMimeTypeOfSendingFiles, mUrisOfSendingFiles,
                    mIsHandoverInitiated);
            if (mMultipleFlag) {
                mfileNumInBatch = mUrisOfSendingFiles.size();
            }
@@ -336,8 +367,11 @@ public class BluetoothOppManager {

        private final boolean mIsMultiple;

        private final boolean mIsHandoverInitiated;

        public InsertShareInfoThread(BluetoothDevice device, boolean multiple,
                String typeOfSingleFile, String uri, String typeOfMultipleFiles, ArrayList<Uri> uris) {
                String typeOfSingleFile, String uri, String typeOfMultipleFiles,
                ArrayList<Uri> uris, boolean handoverInitiated) {
            super("Insert ShareInfo Thread");
            this.mRemoteDevice = device;
            this.mIsMultiple = multiple;
@@ -345,6 +379,7 @@ public class BluetoothOppManager {
            this.mUri = uri;
            this.mTypeOfMultipleFiles = typeOfMultipleFiles;
            this.mUris = uris;
            this.mIsHandoverInitiated = handoverInitiated;

            synchronized (BluetoothOppManager.this) {
                mInsertShareThreadNum++;
@@ -390,7 +425,10 @@ public class BluetoothOppManager {
                values.put(BluetoothShare.MIMETYPE, contentType);
                values.put(BluetoothShare.DESTINATION, mRemoteDevice.getAddress());
                values.put(BluetoothShare.TIMESTAMP, ts);

                if (mIsHandoverInitiated) {
                    values.put(BluetoothShare.USER_CONFIRMATION,
                            BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
                }
                final Uri contentUri = mContext.getContentResolver().insert(
                        BluetoothShare.CONTENT_URI, values);
                if (V) Log.v(TAG, "Insert contentUri: " + contentUri + "  to device: "
@@ -406,7 +444,10 @@ public class BluetoothOppManager {
            values.put(BluetoothShare.URI, mUri);
            values.put(BluetoothShare.MIMETYPE, mTypeOfSingleFile);
            values.put(BluetoothShare.DESTINATION, mRemoteDevice.getAddress());

            if (mIsHandoverInitiated) {
                values.put(BluetoothShare.USER_CONFIRMATION,
                        BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
            }
            final Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI,
                    values);
            if (V) Log.v(TAG, "Insert contentUri: " + contentUri + "  to device: "
Loading