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

Commit a130f0e7 authored by Corey Garst's avatar Corey Garst
Browse files

Bluetooth MAP (Message Access Profile) Upstream Changes (1/3)

Incorporates updates to the Bluetooth MAP profile from Code Aurora's
Android Enablement Project since we initially pulled in from their
gingerbread to CM7 last year. This patch addresses bugs with the
current MAP profile, adds a UI request for message access approval
when pairing, and adds additional error checking and logging.
Confirmed to fix date and "Download" function of Ford SYNC Gen1.
Pulled in from the codeaurora jb branch.

Change-Id: I8e6d793e16c36b77212927e94e8c96d1cf651dcb
parent 0ed3d877
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
    <uses-permission android:name="com.android.email.permission.ACCESS_PROVIDER"></uses-permission>
    <uses-permission android:name="com.android.email.permission.READ_ATTACHMENT"></uses-permission>
    <uses-permission android:name="com.android.permission.HANDOVER_STATUS" />
    <uses-permission android:name="android.permission.MMS_PUSH"></uses-permission>
    <application
        android:icon="@drawable/bt_share"
        android:label="@string/app_name">
+44 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *        * Redistributions of source code must retain the above copyright
 *            notice, this list of conditions and the following disclaimer.
 *        * Redistributions in binary form must reproduce the above copyright
 *            notice, this list of conditions and the following disclaimer in the
 *            documentation and/or other materials provided with the distribution.
 *        * Neither the name of Code Aurora nor
 *            the names of its contributors may be used to endorse or promote
 *            products derived from this software without specific prior written
 *            permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="map_acceptance_dialog_title">%1$s would like to access your phone folders. Give access to %2$s?</string>
    <string name="map_acceptance_dialog_header">Phone Folder Access</string>
    <string name="map_session_key_dialog_title">Type session key for %1$s</string>
    <string name="map_session_key_dialog_header">Bluetooth session key required</string>
    <string name="map_acceptance_timeout_message">There was time out to accept connection with %1$s</string>
    <string name="map_authentication_timeout_message">There was time out to input session key with %1$s</string>
    <string name="map_notif_ticker">Obex authentication request</string>
    <!-- Notification title when a Bluetooth device wants to pair with us -->
    <string name="map_notif_title">Session Key Request for MAP</string>
    <!-- Notification message when a Bluetooth device wants to pair with us -->
    <string name="map_notif_message">Allow root folder access by %1$s</string>
    <string name="map_alert_conn_failed_message">Bluetooth MAP connection failed.</string>
</resources>
+4 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2008-2009, Motorola, Inc.
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -32,7 +33,8 @@ import android.os.Handler;
import android.os.Message;
import android.util.Log;

import javax.obex.*;
import javax.obex.Authenticator;
import javax.obex.PasswordAuthentication;

/**
 * BluetoothMapAuthenticator is a used by BluetoothObexServer for obex
@@ -95,8 +97,7 @@ public class BluetoothMapAuthenticator implements Authenticator {

    // TODO: Reserved for future use only, in case PSE challenge PCE
    public byte[] onAuthenticationResponse(final byte[] userName) {
        byte[] b = null;
        return b;
        return null;
    }
}
+4 −4
Original line number Diff line number Diff line
/*
 * Copyright (c) 2008-2009, Motorola, Inc.
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -28,16 +29,15 @@

package com.android.bluetooth.map;

import android.bluetooth.BluetoothSocket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


import javax.obex.*;

import android.bluetooth.BluetoothSocket;
import javax.obex.ObexTransport;

public class BluetoothMapRfcommTransport implements ObexTransport {
    private BluetoothSocket mSocket = null;
+68 −41
Original line number Diff line number Diff line
 /*
 * Copyright (c) 2008-2009, Motorola, Inc.
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -28,9 +29,7 @@

package com.android.bluetooth.map;

import com.android.bluetooth.R;

import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -40,9 +39,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.text.InputFilter.LengthFilter;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -51,15 +48,19 @@ import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Toast;

import com.android.bluetooth.R;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;

import static com.android.bluetooth.map.BluetoothMasService.EXTRA_BLUETOOTH_DEVICE;

/**
 * MapActivity shows two dialogues: One for accepting incoming ftp request and
 * the other prompts the user to enter a session key for authentication with a
 * remote Bluetooth device.
 */
public class BluetoothMasActivity extends Activity implements
public class BluetoothMasActivity extends AlertActivity implements
        DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener, TextWatcher {
    private static final String TAG = "BluetoothMasActivity";

@@ -69,8 +70,6 @@ public class BluetoothMasActivity extends Activity implements

    private static final int DIALOG_YES_NO_CONNECT = 1;

    private static final int DIALOG_YES_NO_AUTH = 2;

    private static final String KEY_USER_TIMEOUT = "user_timeout";

    private View mView;
@@ -110,12 +109,9 @@ public class BluetoothMasActivity extends Activity implements
        super.onCreate(savedInstanceState);
        Intent i = getIntent();
        String action = i.getAction();
        if (action.equals(BluetoothMasService.ACCESS_REQUEST_ACTION)) {
        if (BluetoothMasService.ACCESS_REQUEST_ACTION.equals(action)) {
            showMapDialog(DIALOG_YES_NO_CONNECT);
            mCurrentDialog = DIALOG_YES_NO_CONNECT;
        } else if (action.equals(BluetoothMasService.AUTH_CHALL_ACTION)) {
            showMapDialog(DIALOG_YES_NO_AUTH);
            mCurrentDialog = DIALOG_YES_NO_AUTH;
        }
        else {
            Log.e(TAG, "Error: this activity may be started only with intent "
@@ -127,20 +123,56 @@ public class BluetoothMasActivity extends Activity implements
    }

    private void showMapDialog(int id) {
        final AlertController.AlertParams p = mAlertParams;
        switch (id) {
            case DIALOG_YES_NO_CONNECT:
                p.mIconId = android.R.drawable.ic_dialog_info;
                p.mTitle = getString(R.string.map_acceptance_dialog_header);
                p.mView = createView(DIALOG_YES_NO_CONNECT);
                p.mPositiveButtonText = getString(android.R.string.yes);
                p.mPositiveButtonListener = this;
                p.mNegativeButtonText = getString(android.R.string.no);
                p.mNegativeButtonListener = this;
                mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
                setupAlert();
                break;
            default:
                break;
        }
    }

    private String getRemoteDeviceName() {
        String remoteDeviceName = null;
        Intent intent = getIntent();
        if (intent.hasExtra(EXTRA_BLUETOOTH_DEVICE)) {
            BluetoothDevice device = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE);
            if (device != null) {
                remoteDeviceName = device.getName();
            }
        }

        return (remoteDeviceName != null) ? remoteDeviceName : getString(R.string.defaultname);
    }

    private String createDisplayText(final int id) {
        String mRemoteName = BluetoothMasService.getRemoteDeviceName();
        String mRemoteName = getRemoteDeviceName();
        switch (id) {
        case DIALOG_YES_NO_CONNECT:
            String mMessage1 = getString(R.string.map_acceptance_dialog_title, mRemoteName,
                    mRemoteName);
            return mMessage1;
        default:
            return null;
        }
    }

    private View createView(final int id) {
        switch (id) {
            case DIALOG_YES_NO_CONNECT:
                mView = getLayoutInflater().inflate(R.layout.access, null);
                //mView = getLayoutInflater().inflate(R.layout.access, null);
                messageView = (TextView)mView.findViewById(R.id.message);
                messageView.setText(createDisplayText(id));
                mAlwaysAllowed = (CheckBox)mView.findViewById(R.id.alwaysallowed);
                //mAlwaysAllowed = (CheckBox)mView.findViewById(R.id.alwaysallowed);
                mAlwaysAllowed.setChecked(true);
                mAlwaysAllowed.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -152,16 +184,6 @@ public class BluetoothMasActivity extends Activity implements
                    }
                });
                return mView;
            case DIALOG_YES_NO_AUTH:
                mView = getLayoutInflater().inflate(R.layout.auth, null);
                messageView = (TextView)mView.findViewById(R.id.message);
                messageView.setText(createDisplayText(id));
                mKeyView = (EditText)mView.findViewById(R.id.text);
                mKeyView.addTextChangedListener(this);
                mKeyView.setFilters(new InputFilter[] {
                    new LengthFilter(BLUETOOTH_OBEX_AUTHKEY_MAX_LENGTH)
                });
                return mView;
            default:
                return null;
        }
@@ -172,10 +194,6 @@ public class BluetoothMasActivity extends Activity implements
            if (mCurrentDialog == DIALOG_YES_NO_CONNECT) {
                sendIntentToReceiver(BluetoothMasService.ACCESS_ALLOWED_ACTION,
                        BluetoothMasService.EXTRA_ALWAYS_ALLOWED, mAlwaysAllowedValue);
            } else if (mCurrentDialog == DIALOG_YES_NO_AUTH) {
                sendIntentToReceiver(BluetoothMasService.AUTH_RESPONSE_ACTION,
                        BluetoothMasService.EXTRA_SESSION_KEY, mSessionKey);
                mKeyView.removeTextChangedListener(this);
            }
        }
        mTimeout = false;
@@ -185,9 +203,6 @@ public class BluetoothMasActivity extends Activity implements
    private void onNegative() {
        if (mCurrentDialog == DIALOG_YES_NO_CONNECT) {
            sendIntentToReceiver(BluetoothMasService.ACCESS_DISALLOWED_ACTION, null, null);
        } else if (mCurrentDialog == DIALOG_YES_NO_AUTH) {
            sendIntentToReceiver(BluetoothMasService.AUTH_CANCELLED_ACTION, null, null);
            mKeyView.removeTextChangedListener(this);
        }
        finish();
    }
@@ -211,15 +226,16 @@ public class BluetoothMasActivity extends Activity implements
        if (extraName != null) {
            intent.putExtra(extraName, extraValue);
        }
        Intent i = getIntent();
        if (i.hasExtra(EXTRA_BLUETOOTH_DEVICE)) {
            intent.putExtra(EXTRA_BLUETOOTH_DEVICE, i.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE));
        }
        sendBroadcast(intent);
    }

    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                if (mCurrentDialog == DIALOG_YES_NO_AUTH) {
                    mSessionKey = mKeyView.getText().toString();
                }
                onPositive();
                break;

@@ -232,19 +248,30 @@ public class BluetoothMasActivity extends Activity implements
    }

    private void onTimeout() {
        mTimeout = true;
        if (mCurrentDialog == DIALOG_YES_NO_CONNECT) {
            if(mView != null) {
                messageView.setText(getString(R.string.map_acceptance_timeout_message,
                        getRemoteDeviceName()));
                mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
                mAlwaysAllowed.setVisibility(View.GONE);
                mAlwaysAllowed.clearFocus();
            }
        }

        mTimeoutHandler.sendMessageDelayed(mTimeoutHandler.obtainMessage(DISMISS_TIMEOUT_DIALOG),
                DISMISS_TIMEOUT_DIALOG_VALUE);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mTimeout = savedInstanceState.getBoolean(KEY_USER_TIMEOUT);
        if (V) Log.e(TAG, "onRestoreInstanceState() mTimeout: " + mTimeout);
        if (V) Log.v(TAG, "onRestoreInstanceState() mTimeout: " + mTimeout);

        if (mTimeout) {
            onTimeout();
        }


    }

    @Override
@@ -279,7 +306,7 @@ public class BluetoothMasActivity extends Activity implements
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DISMISS_TIMEOUT_DIALOG:
                    if (V) Log.e(TAG, "Received DISMISS_TIMEOUT_DIALOG msg.");
                    if (V) Log.v(TAG, "Received DISMISS_TIMEOUT_DIALOG msg.");
                    finish();
                    break;
                default:
Loading