summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/settings/SecuritySettings.java80
-rw-r--r--src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java7
-rw-r--r--src/com/android/settings/bluetooth/DockService.java55
-rw-r--r--src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java78
4 files changed, 202 insertions, 18 deletions
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 1348d48..05a655a 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -66,6 +66,10 @@ public class SecuritySettings extends PreferenceActivity {
private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
private static final String KEY_TACTILE_FEEDBACK_ENABLED = "unlock_tactile_feedback";
+ // Encrypted File Systems constants
+ private static final String PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
+ private static final String PROPERTY_EFS_TRANSITION = "persist.security.efs.trans";
+
private CheckBoxPreference mVisiblePattern;
private CheckBoxPreference mTactileFeedback;
@@ -80,6 +84,9 @@ public class SecuritySettings extends PreferenceActivity {
// Credential storage
private CredentialStorage mCredentialStorage = new CredentialStorage();
+ // Encrypted file system
+ private CheckBoxPreference mEncryptedFSEnabled;
+
private CheckBoxPreference mNetwork;
private CheckBoxPreference mGps;
private CheckBoxPreference mAssistedGps;
@@ -209,6 +216,11 @@ public class SecuritySettings extends PreferenceActivity {
root.addPreference(credentialsCat);
mCredentialStorage.createPreferences(credentialsCat, CredentialStorage.TYPE_KEYSTORE);
+ // File System Encryption
+ PreferenceCategory encryptedfsCat = new PreferenceCategory(this);
+ encryptedfsCat.setTitle(R.string.encrypted_fs_category);
+ //root.addPreference(encryptedfsCat);
+ mCredentialStorage.createPreferences(encryptedfsCat, CredentialStorage.TYPE_ENCRYPTEDFS);
return root;
}
@@ -302,18 +314,21 @@ public class SecuritySettings extends PreferenceActivity {
private static final int MINIMUM_PASSWORD_LENGTH = 8;
private static final int TYPE_KEYSTORE = 0;
+ private static final int TYPE_ENCRYPTEDFS = 1;
// Dialog identifiers
private static final int DLG_BASE = 0;
private static final int DLG_UNLOCK = DLG_BASE + 1;
private static final int DLG_PASSWORD = DLG_UNLOCK + 1;
private static final int DLG_RESET = DLG_PASSWORD + 1;
+ private static final int DLG_ENABLE_EFS = DLG_RESET + 1;
private KeyStore mKeyStore = KeyStore.getInstance();
private int mState;
private boolean mSubmit = false;
private boolean mExternal = false;
+ private boolean mWillEnableEncryptedFS;
private int mShowingDialog = 0;
// Key Store controls
@@ -322,6 +337,10 @@ public class SecuritySettings extends PreferenceActivity {
private Preference mPasswordButton;
private Preference mResetButton;
+
+ // Encrypted file system controls
+ private CheckBoxPreference mEncryptedFSEnabled;
+
void resume() {
mState = mKeyStore.test();
updatePreferences(mState);
@@ -373,6 +392,10 @@ public class SecuritySettings extends PreferenceActivity {
lock();
}
return true;
+ } else if (preference == mEncryptedFSEnabled) {
+ Boolean bval = (Boolean)value;
+ mWillEnableEncryptedFS = bval.booleanValue();
+ showSwitchEncryptedFSDialog();
}
return true;
}
@@ -391,9 +414,26 @@ public class SecuritySettings extends PreferenceActivity {
}
public void onClick(DialogInterface dialog, int button) {
- mSubmit = (button == DialogInterface.BUTTON_POSITIVE);
- if (button == DialogInterface.BUTTON_NEUTRAL) {
- reset();
+ if (mShowingDialog != DLG_ENABLE_EFS) {
+ mSubmit = (button == DialogInterface.BUTTON_POSITIVE);
+ if (button == DialogInterface.BUTTON_NEUTRAL) {
+ reset();
+ }
+ } else {
+ if (button == DialogInterface.BUTTON_POSITIVE) {
+ Intent intent = new Intent("android.intent.action.MASTER_CLEAR");
+ intent.putExtra("enableEFS", mWillEnableEncryptedFS);
+ sendBroadcast(intent);
+ updatePreferences(mState);
+ } else if (button == DialogInterface.BUTTON_NEGATIVE) {
+ // Cancel action
+ Toast.makeText(SecuritySettings.this, R.string.encrypted_fs_cancel_confirm,
+ Toast.LENGTH_SHORT).show();
+ updatePreferences(mState);
+ } else {
+ // Unknown - should not happen
+ return;
+ }
}
}
@@ -507,16 +547,25 @@ public class SecuritySettings extends PreferenceActivity {
category.addPreference(mResetButton);
break;
+ case TYPE_ENCRYPTEDFS:
+ mEncryptedFSEnabled = new CheckBoxPreference(SecuritySettings.this);
+ mEncryptedFSEnabled.setTitle(R.string.encrypted_fs_enable);
+ mEncryptedFSEnabled.setSummary(R.string.encrypted_fs_enable_summary);
+ mEncryptedFSEnabled.setOnPreferenceChangeListener(this);
+ // category.addPreference(mEncryptedFSEnabled);
+ break;
}
}
private void updatePreferences(int state) {
mAccessCheckBox.setChecked(state == KeyStore.NO_ERROR);
-
- mResetButton.setEnabled(state != KeyStore.UNINITIALIZED);
- mAccessCheckBox.setEnabled(state != KeyStore.UNINITIALIZED);
+ boolean encFSEnabled = SystemProperties.getBoolean(PROPERTY_EFS_ENABLED,
+ false);
+ mResetButton.setEnabled((!encFSEnabled) && (state != KeyStore.UNINITIALIZED));
+ mAccessCheckBox.setEnabled((state != KeyStore.UNINITIALIZED) && (!encFSEnabled));
// Encrypted File system preferences
+ mEncryptedFSEnabled.setChecked(encFSEnabled);
// Show a toast message if the state is changed.
if (mState == state) {
@@ -586,5 +635,24 @@ public class SecuritySettings extends PreferenceActivity {
.setNegativeButton(getString(android.R.string.cancel), this)
.create().show();
}
+
+ private void showSwitchEncryptedFSDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(SecuritySettings.this)
+ .setCancelable(false)
+ .setTitle(R.string.encrypted_fs_alert_dialog_title);
+
+ mShowingDialog = DLG_ENABLE_EFS;
+ if (mWillEnableEncryptedFS) {
+ builder.setMessage(R.string.encrypted_fs_enable_dialog)
+ .setPositiveButton(R.string.encrypted_fs_enable_button, this)
+ .setNegativeButton(R.string.encrypted_fs_cancel_button, this)
+ .create().show();
+ } else {
+ builder.setMessage(R.string.encrypted_fs_disable_dialog)
+ .setPositiveButton(R.string.encrypted_fs_disable_button, this)
+ .setNegativeButton(R.string.encrypted_fs_cancel_button, this)
+ .create().show();
+ }
+ }
}
}
diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
index 08534f3..2a8af5f 100644
--- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
+++ b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
@@ -179,6 +179,9 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
private void onProfileCheckedStateChanged(Profile profile, boolean checked) {
+ LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
+ .getProfileManager(mManager, profile);
+ profileManager.setPreferred(mCachedDevice.getDevice(), checked);
if (mOnlineMode) {
if (checked) {
mCachedDevice.connect(profile);
@@ -186,10 +189,6 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
mCachedDevice.disconnect(profile);
}
}
-
- LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
- .getProfileManager(mManager, profile);
- profileManager.setPreferred(mCachedDevice.getDevice(), checked);
}
public void onDeviceAttributesChanged(CachedBluetoothDevice cachedDevice) {
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
index f318987..d0f8099 100644
--- a/src/com/android/settings/bluetooth/DockService.java
+++ b/src/com/android/settings/bluetooth/DockService.java
@@ -18,6 +18,7 @@ package com.android.settings.bluetooth;
import com.android.settings.R;
import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.ServiceListener;
import android.app.AlertDialog;
import android.app.Notification;
@@ -48,7 +49,7 @@ import java.util.Set;
public class DockService extends Service implements AlertDialog.OnMultiChoiceClickListener,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
- CompoundButton.OnCheckedChangeListener {
+ CompoundButton.OnCheckedChangeListener, ServiceListener {
private static final String TAG = "DockService";
@@ -101,6 +102,7 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
// Created in OnCreate()
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
+ private Runnable mRunnable;
private DockService mContext;
private LocalBluetoothManager mBtManager;
@@ -138,6 +140,8 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
@Override
public void onDestroy() {
if (DEBUG) Log.d(TAG, "onDestroy");
+ mRunnable = null;
+ LocalBluetoothProfileManager.removeServiceListener(this);
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
@@ -228,8 +232,8 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
// This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper
private synchronized void processMessage(Message msg) {
int msgType = msg.what;
- int state = msg.arg1;
- int startId = msg.arg2;
+ final int state = msg.arg1;
+ final int startId = msg.arg2;
boolean deferFinishCall = false;
BluetoothDevice device = null;
if (msg.obj != null) {
@@ -271,12 +275,23 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
}
mDevice = device;
- if (mBtManager.getDockAutoConnectSetting(device.getAddress())) {
- // Setting == auto connect
- initBtSettings(mContext, device, state, false);
- applyBtSettings(mDevice, startId);
+
+ // Register first in case LocalBluetoothProfileManager
+ // becomes ready after isManagerReady is called and it
+ // would be too late to register a service listener.
+ LocalBluetoothProfileManager.addServiceListener(this);
+ if (LocalBluetoothProfileManager.isManagerReady()) {
+ handleDocked(device, state, startId);
+ // Not needed after all
+ LocalBluetoothProfileManager.removeServiceListener(this);
} else {
- createDialog(mContext, mDevice, state, startId);
+ final BluetoothDevice d = device;
+ mRunnable = new Runnable() {
+ public void run() {
+ handleDocked(d, state, startId);
+ }
+ };
+ deferFinishCall = true;
}
}
break;
@@ -721,8 +736,21 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
}
}
+ private synchronized void handleDocked(final BluetoothDevice device, final int state,
+ final int startId) {
+ if (mBtManager.getDockAutoConnectSetting(device.getAddress())) {
+ // Setting == auto connect
+ initBtSettings(mContext, device, state, false);
+ applyBtSettings(mDevice, startId);
+ } else {
+ createDialog(mContext, device, state, startId);
+ }
+ }
+
private synchronized void handleUndocked(Context context, LocalBluetoothManager localManager,
BluetoothDevice device) {
+ mRunnable = null;
+ LocalBluetoothProfileManager.removeServiceListener(this);
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
@@ -778,4 +806,15 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
editor.commit();
return;
}
+
+ public synchronized void onServiceConnected() {
+ if (mRunnable != null) {
+ mRunnable.run();
+ mRunnable = null;
+ LocalBluetoothProfileManager.removeServiceListener(this);
+ }
+ }
+
+ public void onServiceDisconnected() {
+ }
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
index f3aaade..6179dc7 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
@@ -28,6 +28,8 @@ import android.util.Log;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -53,6 +55,29 @@ public abstract class LocalBluetoothProfileManager {
BluetoothUuid.ObexObjectPush
};
+ /**
+ * An interface for notifying BluetoothHeadset IPC clients when they have
+ * been connected to the BluetoothHeadset service.
+ */
+ public interface ServiceListener {
+ /**
+ * Called to notify the client when this proxy object has been
+ * connected to the BluetoothHeadset service. Clients must wait for
+ * this callback before making IPC calls on the BluetoothHeadset
+ * service.
+ */
+ public void onServiceConnected();
+
+ /**
+ * Called to notify the client that this proxy object has been
+ * disconnected from the BluetoothHeadset service. Clients must not
+ * make IPC calls on the BluetoothHeadset service after this callback.
+ * This callback will currently only occur if the application hosting
+ * the BluetoothHeadset service, but may be called more often in future.
+ */
+ public void onServiceDisconnected();
+ }
+
// TODO: close profiles when we're shutting down
private static Map<Profile, LocalBluetoothProfileManager> sProfileMap =
new HashMap<Profile, LocalBluetoothProfileManager>();
@@ -76,6 +101,26 @@ public abstract class LocalBluetoothProfileManager {
}
}
+ private static LinkedList<ServiceListener> mServiceListeners = new LinkedList<ServiceListener>();
+
+ public static void addServiceListener(ServiceListener l) {
+ mServiceListeners.add(l);
+ }
+
+ public static void removeServiceListener(ServiceListener l) {
+ mServiceListeners.remove(l);
+ }
+
+ public static boolean isManagerReady() {
+ // Getting just the headset profile is fine for now. Will need to deal with A2DP
+ // and others if they aren't always in a ready state.
+ LocalBluetoothProfileManager profileManager = sProfileMap.get(Profile.HEADSET);
+ if (profileManager == null) {
+ return sProfileMap.size() > 0;
+ }
+ return profileManager.isProfileReady();
+ }
+
public static LocalBluetoothProfileManager getProfileManager(LocalBluetoothManager localManager,
Profile profile) {
// Note: This code assumes that "localManager" is same as the
@@ -144,6 +189,8 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.isConnectionStatusConnected(getConnectionStatus(device));
}
+ public abstract boolean isProfileReady();
+
// TODO: int instead of enum
public enum Profile {
HEADSET(R.string.bluetooth_profile_headset),
@@ -247,6 +294,11 @@ public abstract class LocalBluetoothProfileManager {
return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
}
}
+
+ @Override
+ public boolean isProfileReady() {
+ return true;
+ }
}
/**
@@ -256,6 +308,7 @@ public abstract class LocalBluetoothProfileManager {
implements BluetoothHeadset.ServiceListener {
private BluetoothHeadset mService;
private Handler mUiHandler = new Handler();
+ private boolean profileReady = false;
public HeadsetProfileManager(LocalBluetoothManager localManager) {
super(localManager);
@@ -263,6 +316,7 @@ public abstract class LocalBluetoothProfileManager {
}
public void onServiceConnected() {
+ profileReady = true;
// This could be called on a non-UI thread, funnel to UI thread.
mUiHandler.post(new Runnable() {
public void run() {
@@ -277,9 +331,28 @@ public abstract class LocalBluetoothProfileManager {
BluetoothHeadset.STATE_CONNECTED);
}
});
+
+ if (mServiceListeners.size() > 0) {
+ Iterator<ServiceListener> it = mServiceListeners.iterator();
+ while(it.hasNext()) {
+ it.next().onServiceConnected();
+ }
+ }
}
public void onServiceDisconnected() {
+ profileReady = false;
+ if (mServiceListeners.size() > 0) {
+ Iterator<ServiceListener> it = mServiceListeners.iterator();
+ while(it.hasNext()) {
+ it.next().onServiceDisconnected();
+ }
+ }
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return profileReady;
}
@Override
@@ -424,6 +497,11 @@ public abstract class LocalBluetoothProfileManager {
}
@Override
+ public boolean isProfileReady() {
+ return true;
+ }
+
+ @Override
public int convertState(int oppState) {
switch (oppState) {
case 0: