diff options
author | Matthew Xie <mattx@google.com> | 2011-08-08 20:29:18 -0700 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2011-08-18 16:31:30 -0700 |
commit | b707255a440e53ec2865c4b34c7ea07d16d471bd (patch) | |
tree | 4992ff5c27cef5081589c92ee48bae0dec45b67e | |
parent | 9403d8b2397cac1cb90e59eab1704a8df377149a (diff) | |
download | packages_apps_Settings-b707255a440e53ec2865c4b34c7ea07d16d471bd.zip packages_apps_Settings-b707255a440e53ec2865c4b34c7ea07d16d471bd.tar.gz packages_apps_Settings-b707255a440e53ec2865c4b34c7ea07d16d471bd.tar.bz2 |
Remember user choice for phone book access permission dialog
Change the always-allowed checkbox to be don't-ask-again checkbox to remember
user's decision so that user will not be bothered agian if he/she checks
the don't-ask-again checkbox
bug 5099661
Change-Id: If32ab8e93313bbd33ff040553083f0cf9359b69e
7 files changed, 212 insertions, 53 deletions
diff --git a/res/layout/bluetooth_pb_access.xml b/res/layout/bluetooth_pb_access.xml index 80f78a6..24f0df2 100644 --- a/res/layout/bluetooth_pb_access.xml +++ b/res/layout/bluetooth_pb_access.xml @@ -36,12 +36,12 @@ android:gravity="center_horizontal" android:textAppearance="?android:attr/textAppearanceMedium" /> - <CheckBox android:id="@+id/bluetooth_pb_alwaysallowed" + <CheckBox android:id="@+id/bluetooth_pb_remember_choice" style="?android:attr/textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="2dip" - android:text="@string/bluetooth_pb_alwaysallowed" /> + android:text="@string/bluetooth_pb_remember_choice" /> </LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index b777fd7..65875b0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -323,7 +323,7 @@ <string name="bluetooth_pb_acceptance_dialog_text">%1$s would like to access your contacts and call history. Give access to %2$s?</string> <!-- Bluetooth phone book permission Alert Activity checkbox text [CHAR LIMIT=none] --> - <string name="bluetooth_pb_alwaysallowed">Always allowed?</string> + <string name="bluetooth_pb_remember_choice">Don\'t ask again</string> <!-- Date & time settings screen title --> <string name="date_and_time">Date & time settings</string> diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java index 4d96140..4fd6cee 100644 --- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java @@ -53,13 +53,12 @@ public class BluetoothPermissionActivity extends AlertActivity implements private TextView messageView; private Button mOkButton; private BluetoothDevice mDevice; - - private CheckBox mAlwaysAllowed; - private boolean mAlwaysAllowedValue = true; - private String mReturnPackage = null; private String mReturnClass = null; + private CheckBox mRememberChoice; + private boolean mRememberChoiceValue = false; + private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -70,6 +69,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements } } }; + private boolean mReceiverRegistered = false; private void dismissDialog() { this.dismiss(); @@ -81,26 +81,31 @@ public class BluetoothPermissionActivity extends AlertActivity implements Intent i = getIntent(); String action = i.getAction(); + if (!action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) { + Log.e(TAG, "Error: this activity may be started only with intent " + + "ACTION_CONNECTION_ACCESS_REQUEST"); + finish(); + return; + } + mDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); mReturnPackage = i.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME); mReturnClass = i.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME); + int requestType = i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); - if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) { - mDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - if (i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, - BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) == - BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) { - showConnectionDialog(); - } else { - showPbapDialog(); - } + if (requestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) { + showConnectionDialog(); + } else if (requestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) { + showPhonebookDialog(); } else { - Log.e(TAG, "Error: this activity may be started only with intent " - + "ACTION_CONNECTION_ACCESS_REQUEST"); + Log.e(TAG, "Error: bad request type: " + requestType); finish(); + return; } registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)); + mReceiverRegistered = true; } private void showConnectionDialog() { @@ -116,11 +121,11 @@ public class BluetoothPermissionActivity extends AlertActivity implements setupAlert(); } - private void showPbapDialog() { + private void showPhonebookDialog() { final AlertController.AlertParams p = mAlertParams; p.mIconId = android.R.drawable.ic_dialog_info; p.mTitle = getString(R.string.bluetooth_phonebook_request); - p.mView = createPbapDialogView(); + p.mView = createPhonebookDialogView(); p.mPositiveButtonText = getString(android.R.string.yes); p.mPositiveButtonListener = this; p.mNegativeButtonText = getString(android.R.string.no); @@ -138,7 +143,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements return mMessage1; } - private String createPbapDisplayText() { + private String createPhonebookDisplayText() { String mRemoteName = mDevice != null ? mDevice.getAliasName() : null; if (mRemoteName == null) mRemoteName = getString(R.string.unknown); @@ -154,18 +159,18 @@ public class BluetoothPermissionActivity extends AlertActivity implements return mView; } - private View createPbapDialogView() { + private View createPhonebookDialogView() { mView = getLayoutInflater().inflate(R.layout.bluetooth_pb_access, null); messageView = (TextView)mView.findViewById(R.id.message); - messageView.setText(createPbapDisplayText()); - mAlwaysAllowed = (CheckBox)mView.findViewById(R.id.bluetooth_pb_alwaysallowed); - mAlwaysAllowed.setChecked(true); - mAlwaysAllowed.setOnCheckedChangeListener(new OnCheckedChangeListener() { + messageView.setText(createPhonebookDisplayText()); + mRememberChoice = (CheckBox)mView.findViewById(R.id.bluetooth_pb_remember_choice); + mRememberChoice.setChecked(false); + mRememberChoice.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { - mAlwaysAllowedValue = true; + mRememberChoiceValue = true; } else { - mAlwaysAllowedValue = false; + mRememberChoiceValue = false; } } }); @@ -173,14 +178,22 @@ public class BluetoothPermissionActivity extends AlertActivity implements } private void onPositive() { - if (DEBUG) Log.d(TAG, "onPositive mAlwaysAllowedValue: " + mAlwaysAllowedValue); + if (DEBUG) Log.d(TAG, "onPositive mRememberChoiceValue: " + mRememberChoiceValue); + + if (mRememberChoiceValue) { + savePhonebookPermissionChoice(CachedBluetoothDevice.PHONEBOOK_ACCESS_ALLOWED); + } sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, true, - BluetoothDevice.EXTRA_ALWAYS_ALLOWED, mAlwaysAllowedValue); + BluetoothDevice.EXTRA_ALWAYS_ALLOWED, mRememberChoiceValue); finish(); } private void onNegative() { - if (DEBUG) Log.d(TAG, "onNegative mAlwaysAllowedValue: " + mAlwaysAllowedValue); + if (DEBUG) Log.d(TAG, "onNegative mRememberChoiceValue: " + mRememberChoiceValue); + + if (mRememberChoiceValue) { + savePhonebookPermissionChoice(CachedBluetoothDevice.PHONEBOOK_ACCESS_REJECTED); + } sendIntentToReceiver(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY, false, null, false // dummy value, no effect since last param is null ); @@ -223,10 +236,21 @@ public class BluetoothPermissionActivity extends AlertActivity implements @Override protected void onDestroy() { super.onDestroy(); - unregisterReceiver(mReceiver); + if (mReceiverRegistered) { + unregisterReceiver(mReceiver); + mReceiverRegistered = false; + } } public boolean onPreferenceChange(Preference preference, Object newValue) { return true; } + + private void savePhonebookPermissionChoice(int permissionChoice) { + LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(this); + CachedBluetoothDeviceManager cachedDeviceManager = + bluetoothManager.getCachedDeviceManager(); + CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice); + cachedDevice.setPhonebookPermissionChoice(permissionChoice); + } } diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java index 51055af..e2231bb 100644 --- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java @@ -38,30 +38,44 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { private static final boolean DEBUG = Utils.V; public static final int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth; + Context mContext; + int mRequestType; + BluetoothDevice mDevice; + String mReturnPackage = null; + String mReturnClass = null; + @Override public void onReceive(Context context, Intent intent) { + mContext = context; String action = intent.getAction(); if (DEBUG) Log.d(TAG, "onReceive"); if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) { // convert broadcast intent into activity intent (same action string) - BluetoothDevice device = - intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + mRequestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION); - String returnPackage = intent.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME); - String returnClass = intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME); + mReturnPackage = intent.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME); + mReturnClass = intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME); Intent connectionAccessIntent = new Intent(action); connectionAccessIntent.setClass(context, BluetoothPermissionActivity.class); connectionAccessIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, requestType); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, returnPackage); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME, returnClass); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + mRequestType); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, mReturnPackage); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME, 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. + if (checkUserChoice()) { + return; + } - String deviceAddress = device != null ? device.getAddress() : null; + String deviceAddress = mDevice != null ? mDevice.getAddress() : null; PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); @@ -76,14 +90,15 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { // "Clear All Notifications" button Intent deleteIntent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); - deleteIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + deleteIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); deleteIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, BluetoothDevice.CONNECTION_ACCESS_NO); - Notification notification = new Notification(android.R.drawable.stat_sys_data_bluetooth, + Notification notification = new Notification( + android.R.drawable.stat_sys_data_bluetooth, context.getString(R.string.bluetooth_connection_permission_request), System.currentTimeMillis()); - String deviceName = device != null ? device.getAliasName() : null; + String deviceName = mDevice != null ? mDevice.getAliasName() : null; notification.setLatestEventInfo(context, context.getString(R.string.bluetooth_connection_permission_request), context.getString(R.string.bluetooth_connection_notif_message, deviceName), @@ -103,5 +118,68 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { .getSystemService(Context.NOTIFICATION_SERVICE); manager.cancel(NOTIFICATION_ID); } - } + } + + /** + * @return true user had made a choice, this method replies to the request according + * to user's previous decision + * false user hadnot made any choice on this device + */ + private boolean checkUserChoice() { + boolean processed = false; + + // we only remember PHONEBOOK permission + if (mRequestType != BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) { + return processed; + } + + LocalBluetoothManager bluetoothManager = LocalBluetoothManager.getInstance(mContext); + CachedBluetoothDeviceManager cachedDeviceManager = + bluetoothManager.getCachedDeviceManager(); + CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice); + + if (cachedDevice == null) { + cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(), + bluetoothManager.getProfileManager(), mDevice); + } + + int phonebookPermission = cachedDevice.getPhonebookPermissionChoice(); + + if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_UNKNOWN) { + return processed; + } + + String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY; + if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_ALLOWED) { + sendIntentToReceiver(intentName, true, BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true); + processed = true; + } else if (phonebookPermission == CachedBluetoothDevice.PHONEBOOK_ACCESS_REJECTED) { + sendIntentToReceiver(intentName, false, + null, false // dummy value, no effect since previous param is null + ); + processed = true; + } else { + Log.e(TAG, "Bad phonebookPermission: " + phonebookPermission); + } + return processed; + } + + private void sendIntentToReceiver(final String intentName, final boolean allowed, + final String extraName, final boolean extraValue) { + Intent intent = new Intent(intentName); + + 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); + } + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN); + } } diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index 8082314..01fd1b2 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -19,6 +19,8 @@ package com.android.settings.bluetooth; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.content.SharedPreferences; import android.os.ParcelUuid; import android.os.SystemClock; import android.text.TextUtils; @@ -40,6 +42,7 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { private static final String TAG = "CachedBluetoothDevice"; private static final boolean DEBUG = Utils.V; + private final Context mContext; private final LocalBluetoothAdapter mLocalAdapter; private final LocalBluetoothProfileManager mProfileManager; private final BluetoothDevice mDevice; @@ -60,8 +63,20 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { private boolean mVisible; + private int mPhonebookPermissionChoice; + private final Collection<Callback> mCallbacks = new ArrayList<Callback>(); + // Following constants indicate the user's choices of Phone book access settings + // User hasn't made any choice or settings app has wiped out the memory + final static int PHONEBOOK_ACCESS_UNKNOWN = 0; + // User has accepted the connection and let Settings app remember the decision + final static int PHONEBOOK_ACCESS_ALLOWED = 1; + // User has rejected the connection and let Settings app remember the decision + final static int PHONEBOOK_ACCESS_REJECTED = 2; + + private final static String PHONEBOOK_PREFS_NAME = "bluetooth_phonebook_permission"; + /** * When we connect to multiple profiles, we only want to display a single * error even if they all fail. This tracks that state. @@ -125,9 +140,11 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { } } - CachedBluetoothDevice(LocalBluetoothAdapter adapter, - LocalBluetoothProfileManager profileManager, - BluetoothDevice device) { + CachedBluetoothDevice(Context context, + LocalBluetoothAdapter adapter, + LocalBluetoothProfileManager profileManager, + BluetoothDevice device) { + mContext = context; mLocalAdapter = adapter; mProfileManager = profileManager; mDevice = device; @@ -305,9 +322,9 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { fetchName(); fetchBtClass(); updateProfiles(); + fetchPhonebookPermissionChoice(); mVisible = false; - dispatchAttributesChanged(); } @@ -470,6 +487,7 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { if (bondState == BluetoothDevice.BOND_NONE) { mProfiles.clear(); mConnectAfterPairing = false; // cancel auto-connect + setPhonebookPermissionChoice(PHONEBOOK_ACCESS_UNKNOWN); } refresh(); @@ -580,4 +598,28 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { public interface Callback { void onDeviceAttributesChanged(); } + + int getPhonebookPermissionChoice() { + return mPhonebookPermissionChoice; + } + + void setPhonebookPermissionChoice(int permissionChoice) { + SharedPreferences.Editor editor = + mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, Context.MODE_PRIVATE).edit(); + if (permissionChoice == PHONEBOOK_ACCESS_UNKNOWN) { + editor.remove(mDevice.getAddress()); + } else { + editor.putInt(mDevice.getAddress(), permissionChoice); + } + editor.commit(); + mPhonebookPermissionChoice = permissionChoice; + } + + private void fetchPhonebookPermissionChoice() { + SharedPreferences preference = mContext.getSharedPreferences(PHONEBOOK_PREFS_NAME, + Context.MODE_PRIVATE); + mPhonebookPermissionChoice = preference.getInt(mDevice.getAddress(), + PHONEBOOK_ACCESS_UNKNOWN); + } + } diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java b/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java index b511cb3..77f6b2c 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java @@ -17,6 +17,8 @@ package com.android.settings.bluetooth; import android.bluetooth.BluetoothDevice; +import android.content.Context; +import android.util.Log; import java.util.ArrayList; import java.util.Collection; @@ -26,10 +28,17 @@ import java.util.List; * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. */ final class CachedBluetoothDeviceManager { + private static final String TAG = "CachedBluetoothDeviceManager"; + private static final boolean DEBUG = Utils.D; + private Context mContext; private final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>(); + CachedBluetoothDeviceManager(Context context) { + mContext = context; + } + public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() { return new ArrayList<CachedBluetoothDevice>(mCachedDevices); } @@ -74,8 +83,8 @@ final class CachedBluetoothDeviceManager { CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter, LocalBluetoothProfileManager profileManager, BluetoothDevice device) { - CachedBluetoothDevice newDevice = new CachedBluetoothDevice(adapter, profileManager, - device); + CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter, + profileManager, device); mCachedDevices.add(newDevice); return newDevice; } @@ -124,4 +133,10 @@ final class CachedBluetoothDeviceManager { cachedDevice.onUuidChanged(); } } + + private void log(String msg) { + if (DEBUG) { + Log.d(TAG, msg); + } + } } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java index 3357e59..ae8dec2 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java @@ -74,7 +74,7 @@ public final class LocalBluetoothManager { mContext = context; mLocalAdapter = adapter; - mCachedDeviceManager = new CachedBluetoothDeviceManager(); + mCachedDeviceManager = new CachedBluetoothDeviceManager(context); mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, context); mProfileManager = new LocalBluetoothProfileManager(context, |