OSDN Git Service

Migrates PBAP and MAP access permission data from Settings to Bluetooth.
authorEdward Jee <edjee@google.com>
Mon, 8 Sep 2014 23:45:29 +0000 (16:45 -0700)
committerEdward Jee <edjee@google.com>
Tue, 16 Sep 2014 01:25:47 +0000 (01:25 +0000)
Currently, users' preference in phonebook and call history or message
access per each Bluetooth-paired device is stored in Settings application's
shared preferences.

However, some privileged applications other than Settings need to access
such data. So we decided to migrate the data from Settings application's
shared preferences to Bluetooth application's.

Bug: 17158953
Change-Id: I44fde350ea35027df0de77feec1ea19c65f2f1c6

src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
src/com/android/settings/bluetooth/CachedBluetoothDevice.java

index 5426f52..f43d176 100755 (executable)
@@ -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;
@@ -62,7 +59,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements
             String action = intent.getAction();
             if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) {
                 int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
-                                               BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
+                        BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS);
                 if (requestType != mRequestType) return;
                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                 if (mDevice.equals(device)) dismissDialog();
@@ -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();
+        }
+
+        sendReplyIntentToReceiver(false, always);
     }
 
-    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, 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);
-        }
-    }
-
 }
index 1ede05b..bcd4d77 100644 (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);
index c1e75c0..6d2222e 100755 (executable)
@@ -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;
-
-        SharedPreferences.Editor editor =
-            mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, Context.MODE_PRIVATE).edit();
-        if (permissionChoice == ACCESS_UNKNOWN) {
-            editor.remove(mDevice.getAddress());
-        } else {
-            editor.putInt(mDevice.getAddress(), permissionChoice);
+        int permission = BluetoothDevice.ACCESS_UNKNOWN;
+        if (permissionChoice == ACCESS_ALLOWED) {
+            permission = BluetoothDevice.ACCESS_ALLOWED;
+        } else if (permissionChoice == ACCESS_REJECTED) {
+            permission = BluetoothDevice.ACCESS_REJECTED;
         }
-        editor.commit();
+        mDevice.setPhonebookAccessPermission(permission);
     }
 
-    private void fetchPhonebookPermissionChoice() {
-        SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME,
-                                                                     Context.MODE_PRIVATE);
-        mPhonebookPermissionChoice = preference.getInt(mDevice.getAddress(),
-                                                       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());
+        editor.commit();
     }
 
     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) {
-                return;
-            }
+        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);
+    }
 
-        mMessagePermissionChoice = permissionChoice;
+    // 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;
+        }
 
-        SharedPreferences.Editor editor =
-            mContext.getSharedPreferences(MESSAGE_PREFS_NAME, Context.MODE_PRIVATE).edit();
-        if (permissionChoice == ACCESS_UNKNOWN) {
-            editor.remove(mDevice.getAddress());
-        } else {
-            editor.putInt(mDevice.getAddress(), permissionChoice);
+        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);
+            }
         }
+
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.remove(mDevice.getAddress());
         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();
     }
-
 }