am ac8b5b7f: Migrates PBAP and MAP access permission data from Settings to Bluetooth.

* commit 'ac8b5b7fd6b6774d22d39bb9a4becca1908915c7':
  Migrates PBAP and MAP access permission data from Settings to Bluetooth.
This commit is contained in:
Edward Jee
2014-09-16 08:31:59 +00:00
committed by Android Git Automerger
3 changed files with 175 additions and 157 deletions

View File

@@ -26,11 +26,8 @@ import android.os.Bundle;
import android.preference.Preference;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Button;
import android.widget.CompoundButton.OnCheckedChangeListener;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
@@ -186,40 +183,43 @@ public class BluetoothPermissionActivity extends AlertActivity implements
private void onPositive() {
if (DEBUG) Log.d(TAG, "onPositive");
savePermissionChoice(mRequestType, CachedBluetoothDevice.ACCESS_ALLOWED);
// TODO(edjee): Now that we always save the user's choice,
// we can get rid of BluetoothDevice#EXTRA_ALWAYS_ALLOWED.
sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, true,
BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
sendReplyIntentToReceiver(true, true);
finish();
}
private void onNegative() {
if (DEBUG) Log.d(TAG, "onNegative");
savePermissionChoice(mRequestType, CachedBluetoothDevice.ACCESS_REJECTED);
sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, false,
null, false // dummy value, no effect since last param is null
);
finish();
boolean always = true;
if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(this);
CachedBluetoothDeviceManager cachedDeviceManager =
bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (cachedDevice == null) {
cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
bluetoothManager.getProfileManager(),
mDevice);
}
always = cachedDevice.checkAndIncreaseMessageRejectionCount();
}
private void sendIntentToReceiver(final String intentName, final boolean allowed,
final String extraName, final boolean extraValue) {
Intent intent = new Intent(intentName);
sendReplyIntentToReceiver(false, always);
}
private void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
if (mReturnPackage != null && mReturnClass != null) {
intent.setClassName(mReturnPackage, mReturnClass);
}
if(DEBUG) Log.i(TAG, "sendIntentToReceiver() Request type: " + mRequestType +
if (DEBUG) Log.i(TAG, "sendReplyIntentToReceiver() Request type: " + mRequestType +
" mReturnPackage" + mReturnPackage + " mReturnClass" + mReturnClass);
intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
allowed ? BluetoothDevice.CONNECTION_ACCESS_YES :
BluetoothDevice.CONNECTION_ACCESS_NO);
if (extraName != null) {
intent.putExtra(extraName, extraValue);
}
allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
: BluetoothDevice.CONNECTION_ACCESS_NO);
intent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, always);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType);
sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN);
@@ -251,23 +251,4 @@ public class BluetoothPermissionActivity extends AlertActivity implements
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
private void savePermissionChoice(int permissionType, int permissionChoice) {
LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(this);
CachedBluetoothDeviceManager cachedDeviceManager =
bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (DEBUG) Log.d(TAG, "savePermissionChoice permissionType: " + permissionType);
if (cachedDevice == null ) {
cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
bluetoothManager.getProfileManager(),
mDevice);
}
if(permissionType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS){
cachedDevice.setPhonebookPermissionChoice(permissionChoice);
}else if (permissionType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS){
cachedDevice.setMessagePermissionChoice(permissionChoice);
}
}
}

View File

@@ -66,20 +66,30 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
if (DEBUG) Log.d(TAG, "onReceive request type: " + mRequestType + " return "
+ mReturnPackage + "," + mReturnClass);
// Check if user had made decisions on accepting or rejecting the phonebook access
// request. If there is, reply the request and return, no need to start permission
// activity dialog or notification.
// Even if the user has already made the choice, Bluetooth still may not know that if
// the user preference data have not been migrated from Settings app's shared
// preferences to Bluetooth app's. In that case, Bluetooth app broadcasts an
// ACTION_CONNECTION_ACCESS_REQUEST intent to ask to Settings app.
//
// If that happens, 'checkUserChoice()' here will do migration because it finds or
// creates a 'CachedBluetoothDevice' object for the device.
//
// After migration is done, 'checkUserChoice()' replies to the request by sending an
// ACTION_CONNECTION_ACCESS_REPLY intent. And we don't need to start permission activity
// dialog or notification.
if (checkUserChoice()) {
return;
}
Intent connectionAccessIntent = new Intent(action);
connectionAccessIntent.setClass(context, BluetoothPermissionActivity.class);
// We use the FLAG_ACTIVITY_MULTIPLE_TASK since we can have multiple concurrent access requests
connectionAccessIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
connectionAccessIntent.setType(Integer.toString(mRequestType)); /* This is needed to create two pending
intents to the same activity.
The value is not used in the activity. */
// We use the FLAG_ACTIVITY_MULTIPLE_TASK since we can have multiple concurrent access
// requests.
connectionAccessIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
// This is needed to create two pending intents to the same activity. The value is not
// used in the activity.
connectionAccessIntent.setType(Integer.toString(mRequestType));
connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
mRequestType);
connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
@@ -92,8 +102,9 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager.isScreenOn() &&
LocalBluetoothPreferences.shouldShowDialogInForeground(context, deviceAddress) ) {
if (powerManager.isScreenOn()
&& LocalBluetoothPreferences.shouldShowDialogInForeground(
context, deviceAddress)) {
context.startActivity(connectionAccessIntent);
} else {
// Put up a notification that leads to the dialog
@@ -110,15 +121,18 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
switch (mRequestType) {
case BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS:
title = context.getString(R.string.bluetooth_phonebook_request);
message = context.getString(R.string.bluetooth_pb_acceptance_dialog_text, deviceName, deviceName);
message = context.getString(R.string.bluetooth_pb_acceptance_dialog_text,
deviceName, deviceName);
break;
case BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS:
title = context.getString(R.string.bluetooth_map_request);
message = context.getString(R.string.bluetooth_map_acceptance_dialog_text, deviceName, deviceName);
message = context.getString(R.string.bluetooth_map_acceptance_dialog_text,
deviceName, deviceName);
break;
default:
title = context.getString(R.string.bluetooth_connection_permission_request);
message = context.getString(R.string.bluetooth_connection_dialog_text, deviceName, deviceName);
message = context.getString(R.string.bluetooth_connection_dialog_text,
deviceName, deviceName);
break;
}
Notification notification = new Notification.Builder(context)
@@ -137,12 +151,13 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
com.android.internal.R.color.system_notification_accent_color))
.build();
notification.flags |= Notification.FLAG_NO_CLEAR; /* cannot be set with the builder */
notification.flags |= Notification.FLAG_NO_CLEAR; // Cannot be set with the builder.
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(getNotificationTag(mRequestType),NOTIFICATION_ID, notification);
notificationManager.notify(getNotificationTag(mRequestType), NOTIFICATION_ID,
notification);
}
} else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) {
// Remove the notification
@@ -174,7 +189,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
// ignore if it is something else than phonebook/message settings it wants us to remember
if (mRequestType != BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS
&& mRequestType != BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
if (DEBUG) Log.d(TAG, "Unknown RequestType: " + mRequestType);
if (DEBUG) Log.d(TAG, "checkUserChoice(): Unknown RequestType " + mRequestType);
return processed;
}
@@ -182,71 +197,56 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
CachedBluetoothDeviceManager cachedDeviceManager =
bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (cachedDevice == null) {
cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
bluetoothManager.getProfileManager(), mDevice);
}
if(mRequestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) {
String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY;
if (mRequestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) {
int phonebookPermission = cachedDevice.getPhonebookPermissionChoice();
if (phonebookPermission == CachedBluetoothDevice.ACCESS_UNKNOWN) {
return processed;
}
String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY;
if (phonebookPermission == CachedBluetoothDevice.ACCESS_ALLOWED) {
sendIntentToReceiver(intentName, true, BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
// Leave 'processed' as false.
} else if (phonebookPermission == CachedBluetoothDevice.ACCESS_ALLOWED) {
sendReplyIntentToReceiver(true);
processed = true;
} else if (phonebookPermission == CachedBluetoothDevice.ACCESS_REJECTED) {
sendIntentToReceiver(intentName, false,
null, false ); // dummy value, no effect since previous param is null
sendReplyIntentToReceiver(false);
processed = true;
} else {
Log.e(TAG, "Bad phonebookPermission: " + phonebookPermission);
}
} else if(mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
} else if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
int messagePermission = cachedDevice.getMessagePermissionChoice();
if (messagePermission == CachedBluetoothDevice.ACCESS_UNKNOWN) {
return processed;
}
String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY;
if (messagePermission == CachedBluetoothDevice.ACCESS_ALLOWED) {
sendIntentToReceiver(intentName, true, BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
// Leave 'processed' as false.
} else if (messagePermission == CachedBluetoothDevice.ACCESS_ALLOWED) {
sendReplyIntentToReceiver(true);
processed = true;
} else if (messagePermission == CachedBluetoothDevice.ACCESS_REJECTED) {
sendIntentToReceiver(intentName, false,
null, false); // dummy value, no effect since previous param is null
sendReplyIntentToReceiver(false);
processed = true;
} else {
Log.e(TAG, "Bad messagePermission: " + messagePermission);
}
}
if(DEBUG) Log.d(TAG,"checkUserChoice(): returning " + processed);
if (DEBUG) Log.d(TAG,"checkUserChoice(): returning " + processed);
return processed;
}
private void sendIntentToReceiver(final String intentName, final boolean allowed,
final String extraName, final boolean extraValue) {
Intent intent = new Intent(intentName);
private void sendReplyIntentToReceiver(final boolean allowed) {
Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
if (mReturnPackage != null && mReturnClass != null) {
intent.setClassName(mReturnPackage, mReturnClass);
}
intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
allowed ? BluetoothDevice.CONNECTION_ACCESS_YES :
BluetoothDevice.CONNECTION_ACCESS_NO);
if (extraName != null) {
intent.putExtra(extraName, extraValue);
}
allowed ? BluetoothDevice.CONNECTION_ACCESS_YES
: BluetoothDevice.CONNECTION_ACCESS_NO);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType);
mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN);

View File

@@ -68,7 +68,7 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
private int mMessagePermissionChoice;
private int mMessageRejectedTimes;
private int mMessageRejectionCount;
private final Collection<Callback> mCallbacks = new ArrayList<Callback>();
@@ -80,12 +80,10 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
// User has rejected the connection and let Settings app remember the decision
public final static int ACCESS_REJECTED = 2;
// how many times did User reject the connection to make the rejected persist.
final static int PERSIST_REJECTED_TIMES_LIMIT = 2;
// How many times user should reject the connection to make the choice persist.
private final static int MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST = 2;
private final static String PHONEBOOK_PREFS_NAME = "bluetooth_phonebook_permission";
private final static String MESSAGE_PREFS_NAME = "bluetooth_message_permission";
private final static String MESSAGE_REJECT_TIMES = "bluetooth_message_reject";
private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
/**
* When we connect to multiple profiles, we only want to display a single
@@ -367,9 +365,9 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
fetchName();
fetchBtClass();
updateProfiles();
fetchPhonebookPermissionChoice();
fetchMessagePermissionChoice();
fetchMessageRejectTimes();
migratePhonebookPermissionChoice();
migrateMessagePermissionChoice();
fetchMessageRejectionCount();
mVisible = false;
dispatchAttributesChanged();
@@ -537,8 +535,8 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
mConnectAfterPairing = false; // cancel auto-connect
setPhonebookPermissionChoice(ACCESS_UNKNOWN);
setMessagePermissionChoice(ACCESS_UNKNOWN);
mMessageRejectedTimes = 0;
saveMessageRejectTimes();
mMessageRejectionCount = 0;
saveMessageRejectionCount();
}
refresh();
@@ -651,77 +649,116 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
}
int getPhonebookPermissionChoice() {
return mPhonebookPermissionChoice;
int permission = mDevice.getPhonebookAccessPermission();
if (permission == BluetoothDevice.ACCESS_ALLOWED) {
return ACCESS_ALLOWED;
} else if (permission == BluetoothDevice.ACCESS_REJECTED) {
return ACCESS_REJECTED;
}
return ACCESS_UNKNOWN;
}
void setPhonebookPermissionChoice(int permissionChoice) {
mPhonebookPermissionChoice = permissionChoice;
int permission = BluetoothDevice.ACCESS_UNKNOWN;
if (permissionChoice == ACCESS_ALLOWED) {
permission = BluetoothDevice.ACCESS_ALLOWED;
} else if (permissionChoice == ACCESS_REJECTED) {
permission = BluetoothDevice.ACCESS_REJECTED;
}
mDevice.setPhonebookAccessPermission(permission);
}
SharedPreferences.Editor editor =
mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, Context.MODE_PRIVATE).edit();
if (permissionChoice == ACCESS_UNKNOWN) {
// Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
// app's shared preferences).
private void migratePhonebookPermissionChoice() {
SharedPreferences preferences = mContext.getSharedPreferences(
"bluetooth_phonebook_permission", Context.MODE_PRIVATE);
if (!preferences.contains(mDevice.getAddress())) {
return;
}
if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
if (oldPermission == ACCESS_ALLOWED) {
mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
} else if (oldPermission == ACCESS_REJECTED) {
mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
}
}
SharedPreferences.Editor editor = preferences.edit();
editor.remove(mDevice.getAddress());
} else {
editor.putInt(mDevice.getAddress(), permissionChoice);
}
editor.commit();
}
private void fetchPhonebookPermissionChoice() {
SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME,
Context.MODE_PRIVATE);
mPhonebookPermissionChoice = preference.getInt(mDevice.getAddress(),
ACCESS_UNKNOWN);
}
int getMessagePermissionChoice() {
return mMessagePermissionChoice;
int permission = mDevice.getMessageAccessPermission();
if (permission == BluetoothDevice.ACCESS_ALLOWED) {
return ACCESS_ALLOWED;
} else if (permission == BluetoothDevice.ACCESS_REJECTED) {
return ACCESS_REJECTED;
}
return ACCESS_UNKNOWN;
}
void setMessagePermissionChoice(int permissionChoice) {
// if user reject it, only save it when reject exceed limit.
if (permissionChoice == ACCESS_REJECTED) {
mMessageRejectedTimes++;
saveMessageRejectTimes();
if (mMessageRejectedTimes < PERSIST_REJECTED_TIMES_LIMIT) {
int permission = BluetoothDevice.ACCESS_UNKNOWN;
if (permissionChoice == ACCESS_ALLOWED) {
permission = BluetoothDevice.ACCESS_ALLOWED;
} else if (permissionChoice == ACCESS_REJECTED) {
permission = BluetoothDevice.ACCESS_REJECTED;
}
mDevice.setMessageAccessPermission(permission);
}
// Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
// app's shared preferences).
private void migrateMessagePermissionChoice() {
SharedPreferences preferences = mContext.getSharedPreferences(
"bluetooth_message_permission", Context.MODE_PRIVATE);
if (!preferences.contains(mDevice.getAddress())) {
return;
}
if (mDevice.getMessageAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
if (oldPermission == ACCESS_ALLOWED) {
mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
} else if (oldPermission == ACCESS_REJECTED) {
mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED);
}
}
mMessagePermissionChoice = permissionChoice;
SharedPreferences.Editor editor =
mContext.getSharedPreferences(MESSAGE_PREFS_NAME, Context.MODE_PRIVATE).edit();
if (permissionChoice == ACCESS_UNKNOWN) {
SharedPreferences.Editor editor = preferences.edit();
editor.remove(mDevice.getAddress());
} else {
editor.putInt(mDevice.getAddress(), permissionChoice);
}
editor.commit();
}
private void fetchMessagePermissionChoice() {
SharedPreferences preference = mContext.getSharedPreferences(MESSAGE_PREFS_NAME,
Context.MODE_PRIVATE);
mMessagePermissionChoice = preference.getInt(mDevice.getAddress(),
ACCESS_UNKNOWN);
/**
* @return Whether this rejection should persist.
*/
boolean checkAndIncreaseMessageRejectionCount() {
if (mMessageRejectionCount < MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST) {
mMessageRejectionCount++;
saveMessageRejectionCount();
}
return mMessageRejectionCount >= MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST;
}
private void fetchMessageRejectTimes() {
SharedPreferences preference = mContext.getSharedPreferences(MESSAGE_REJECT_TIMES,
Context.MODE_PRIVATE);
mMessageRejectedTimes = preference.getInt(mDevice.getAddress(), 0);
private void fetchMessageRejectionCount() {
SharedPreferences preference = mContext.getSharedPreferences(
MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE);
mMessageRejectionCount = preference.getInt(mDevice.getAddress(), 0);
}
private void saveMessageRejectTimes() {
SharedPreferences.Editor editor =
mContext.getSharedPreferences(MESSAGE_REJECT_TIMES, Context.MODE_PRIVATE).edit();
if (mMessageRejectedTimes == 0) {
private void saveMessageRejectionCount() {
SharedPreferences.Editor editor = mContext.getSharedPreferences(
MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE).edit();
if (mMessageRejectionCount == 0) {
editor.remove(mDevice.getAddress());
} else {
editor.putInt(mDevice.getAddress(), mMessageRejectedTimes);
editor.putInt(mDevice.getAddress(), mMessageRejectionCount);
}
editor.commit();
}
}